From 606f38a2221648ca5c5fa292c9f71d2ddd59fa66 Mon Sep 17 00:00:00 2001
From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Date: Tue, 17 Mar 2009 10:14:54 +0200
Subject: ubi-utils: re-arrange directory layout

Move new-utils to ubi-utils and old ones to ubi-utils/old-utils.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
---
 ubi-utils/.gitignore                             |   19 +-
 ubi-utils/LICENSE.libiniparser                   |   21 +
 ubi-utils/Makefile                               |   64 +-
 ubi-utils/README                                 |  236 ----
 ubi-utils/UBI.TXT                                |  108 --
 ubi-utils/doc/unubi.roff                         |  123 --
 ubi-utils/inc/libubi.h                           |  268 ----
 ubi-utils/include/libiniparser.h                 |  280 ++++
 ubi-utils/include/libmtd.h                       |   73 ++
 ubi-utils/include/libscan.h                      |  112 ++
 ubi-utils/include/libubi.h                       |  394 ++++++
 ubi-utils/include/libubigen.h                    |  110 ++
 ubi-utils/lib/Makefile.am                        |   58 -
 ubi-utils/new-utils/.gitignore                   |   10 -
 ubi-utils/new-utils/LICENSE.libiniparser         |   21 -
 ubi-utils/new-utils/Makefile                     |   57 -
 ubi-utils/new-utils/README                       |   55 -
 ubi-utils/new-utils/include/libiniparser.h       |  280 ----
 ubi-utils/new-utils/include/libmtd.h             |   73 --
 ubi-utils/new-utils/include/libscan.h            |  112 --
 ubi-utils/new-utils/include/libubi.h             |  394 ------
 ubi-utils/new-utils/include/libubigen.h          |  110 --
 ubi-utils/new-utils/src/common.c                 |  194 ---
 ubi-utils/new-utils/src/common.h                 |   85 --
 ubi-utils/new-utils/src/crc32.c                  |   95 --
 ubi-utils/new-utils/src/crc32.h                  |   19 -
 ubi-utils/new-utils/src/dictionary.c             |  405 ------
 ubi-utils/new-utils/src/dictionary.h             |  174 ---
 ubi-utils/new-utils/src/libiniparser.c           |  646 ---------
 ubi-utils/new-utils/src/libmtd.c                 |  314 -----
 ubi-utils/new-utils/src/libscan.c                |  225 ----
 ubi-utils/new-utils/src/libubi.c                 | 1206 -----------------
 ubi-utils/new-utils/src/libubi_int.h             |  133 --
 ubi-utils/new-utils/src/libubigen.c              |  330 -----
 ubi-utils/new-utils/src/ubiattach.c              |  205 ---
 ubi-utils/new-utils/src/ubicrc32.c               |  124 --
 ubi-utils/new-utils/src/ubidetach.c              |  181 ---
 ubi-utils/new-utils/src/ubiformat.c              |  780 -----------
 ubi-utils/new-utils/src/ubimkvol.c               |  313 -----
 ubi-utils/new-utils/src/ubinfo.c                 |  410 ------
 ubi-utils/new-utils/src/ubinize.c                |  612 ---------
 ubi-utils/new-utils/src/ubirename.c              |  141 --
 ubi-utils/new-utils/src/ubirmvol.c               |  230 ----
 ubi-utils/new-utils/src/ubiupdatevol.c           |  355 -----
 ubi-utils/old-utils/.gitignore                   |    9 +
 ubi-utils/old-utils/Makefile                     |   59 +
 ubi-utils/old-utils/README                       |  236 ++++
 ubi-utils/old-utils/UBI.TXT                      |  108 ++
 ubi-utils/old-utils/doc/unubi.roff               |  123 ++
 ubi-utils/old-utils/inc/libubi.h                 |  268 ++++
 ubi-utils/old-utils/lib/Makefile.am              |   58 +
 ubi-utils/old-utils/perl/f128_nand_sample.cfg    |   38 +
 ubi-utils/old-utils/perl/f64_nor_sample.cfg      |   39 +
 ubi-utils/old-utils/perl/mkpfi                   |  723 +++++++++++
 ubi-utils/old-utils/perl/ubicrc32.pl             |   74 ++
 ubi-utils/old-utils/scripts/Makefile             |   75 ++
 ubi-utils/old-utils/scripts/README               |   11 +
 ubi-utils/old-utils/scripts/TODO                 |    5 +
 ubi-utils/old-utils/scripts/bin2nand2bin_test.sh |  184 +++
 ubi-utils/old-utils/scripts/inject_biterror.pl   |   94 ++
 ubi-utils/old-utils/scripts/jffs2_test.sh        |   91 ++
 ubi-utils/old-utils/scripts/mkdevs.pl            |   32 +
 ubi-utils/old-utils/scripts/pdd.txt              |   16 +
 ubi-utils/old-utils/scripts/run_all.sh           |  101 ++
 ubi-utils/old-utils/scripts/test.cfg             |   23 +
 ubi-utils/old-utils/scripts/ubi_jffs2_test.sh    |  411 ++++++
 ubi-utils/old-utils/scripts/ubi_test.sh          |  328 +++++
 ubi-utils/old-utils/scripts/ubi_tools_test.sh    |  252 ++++
 ubi-utils/old-utils/scripts/unubi_test.sh        |  105 ++
 ubi-utils/old-utils/src/bin2nand.c               |  344 +++++
 ubi-utils/old-utils/src/bootenv.c                | 1032 +++++++++++++++
 ubi-utils/old-utils/src/bootenv.h                |  434 +++++++
 ubi-utils/old-utils/src/config.h                 |   28 +
 ubi-utils/old-utils/src/crc32.c                  |   83 ++
 ubi-utils/old-utils/src/crc32.h                  |   36 +
 ubi-utils/old-utils/src/eb_chain.c               |  281 ++++
 ubi-utils/old-utils/src/error.c                  |  240 ++++
 ubi-utils/old-utils/src/error.h                  |   84 ++
 ubi-utils/old-utils/src/example_ubi.h            |   28 +
 ubi-utils/old-utils/src/hashmap.c                |  412 ++++++
 ubi-utils/old-utils/src/hashmap.h                |   49 +
 ubi-utils/old-utils/src/libpfiflash.c            | 1325 +++++++++++++++++++
 ubi-utils/old-utils/src/libubi.c                 |  915 +++++++++++++
 ubi-utils/old-utils/src/libubi_int.h             |  129 ++
 ubi-utils/old-utils/src/libubigen.c              |  487 +++++++
 ubi-utils/old-utils/src/libubimirror.c           |  237 ++++
 ubi-utils/old-utils/src/list.c                   |  149 +++
 ubi-utils/old-utils/src/list.h                   |   56 +
 ubi-utils/old-utils/src/mkbootenv.c              |  168 +++
 ubi-utils/old-utils/src/nand2bin.c               |  493 +++++++
 ubi-utils/old-utils/src/nandcorr.c               |   95 ++
 ubi-utils/old-utils/src/nandecc.c                |  159 +++
 ubi-utils/old-utils/src/nandecc.h                |   29 +
 ubi-utils/old-utils/src/pddcustomize.c           |  516 ++++++++
 ubi-utils/old-utils/src/peb.c                    |  116 ++
 ubi-utils/old-utils/src/peb.h                    |   41 +
 ubi-utils/old-utils/src/pfi.c                    |  458 +++++++
 ubi-utils/old-utils/src/pfi.h                    |  244 ++++
 ubi-utils/old-utils/src/pfi2bin.c                |  682 ++++++++++
 ubi-utils/old-utils/src/pfiflash.c               |  264 ++++
 ubi-utils/old-utils/src/pfiflash.h               |   76 ++
 ubi-utils/old-utils/src/pfiflash_error.h         |   75 ++
 ubi-utils/old-utils/src/reader.c                 |  482 +++++++
 ubi-utils/old-utils/src/reader.h                 |   87 ++
 ubi-utils/old-utils/src/ubigen.c                 |  359 +++++
 ubi-utils/old-utils/src/ubigen.h                 |  149 +++
 ubi-utils/old-utils/src/ubimirror.c              |  213 +++
 ubi-utils/old-utils/src/ubimirror.h              |   66 +
 ubi-utils/old-utils/src/unubi.c                  | 1024 +++++++++++++++
 ubi-utils/old-utils/src/unubi_analyze.c          |  463 +++++++
 ubi-utils/old-utils/src/unubi_analyze.h          |   87 ++
 ubi-utils/old-utils/testcases.txt                |    9 +
 ubi-utils/perl/f128_nand_sample.cfg              |   38 -
 ubi-utils/perl/f64_nor_sample.cfg                |   39 -
 ubi-utils/perl/mkpfi                             |  723 -----------
 ubi-utils/perl/ubicrc32.pl                       |   74 --
 ubi-utils/scripts/Makefile                       |   75 --
 ubi-utils/scripts/README                         |   11 -
 ubi-utils/scripts/TODO                           |    5 -
 ubi-utils/scripts/bin2nand2bin_test.sh           |  184 ---
 ubi-utils/scripts/inject_biterror.pl             |   94 --
 ubi-utils/scripts/jffs2_test.sh                  |   91 --
 ubi-utils/scripts/mkdevs.pl                      |   32 -
 ubi-utils/scripts/pdd.txt                        |   16 -
 ubi-utils/scripts/run_all.sh                     |  101 --
 ubi-utils/scripts/test.cfg                       |   23 -
 ubi-utils/scripts/ubi_jffs2_test.sh              |  411 ------
 ubi-utils/scripts/ubi_test.sh                    |  328 -----
 ubi-utils/scripts/ubi_tools_test.sh              |  252 ----
 ubi-utils/scripts/unubi_test.sh                  |  105 --
 ubi-utils/src/bin2nand.c                         |  344 -----
 ubi-utils/src/bootenv.c                          | 1032 ---------------
 ubi-utils/src/bootenv.h                          |  434 -------
 ubi-utils/src/common.c                           |  194 +++
 ubi-utils/src/common.h                           |   85 ++
 ubi-utils/src/config.h                           |   28 -
 ubi-utils/src/crc32.c                            |  156 +--
 ubi-utils/src/crc32.h                            |   47 +-
 ubi-utils/src/dictionary.c                       |  405 ++++++
 ubi-utils/src/dictionary.h                       |  174 +++
 ubi-utils/src/eb_chain.c                         |  281 ----
 ubi-utils/src/error.c                            |  240 ----
 ubi-utils/src/error.h                            |   84 --
 ubi-utils/src/example_ubi.h                      |   28 -
 ubi-utils/src/hashmap.c                          |  412 ------
 ubi-utils/src/hashmap.h                          |   49 -
 ubi-utils/src/libiniparser.c                     |  646 +++++++++
 ubi-utils/src/libmtd.c                           |  314 +++++
 ubi-utils/src/libpfiflash.c                      | 1325 -------------------
 ubi-utils/src/libscan.c                          |  225 ++++
 ubi-utils/src/libubi.c                           | 1511 +++++++++++++---------
 ubi-utils/src/libubi_int.h                       |   88 +-
 ubi-utils/src/libubigen.c                        |  665 ++++------
 ubi-utils/src/libubimirror.c                     |  237 ----
 ubi-utils/src/list.c                             |  149 ---
 ubi-utils/src/list.h                             |   56 -
 ubi-utils/src/mkbootenv.c                        |  168 ---
 ubi-utils/src/nand2bin.c                         |  493 -------
 ubi-utils/src/nandcorr.c                         |   95 --
 ubi-utils/src/nandecc.c                          |  159 ---
 ubi-utils/src/nandecc.h                          |   29 -
 ubi-utils/src/pddcustomize.c                     |  516 --------
 ubi-utils/src/peb.c                              |  116 --
 ubi-utils/src/peb.h                              |   41 -
 ubi-utils/src/pfi.c                              |  458 -------
 ubi-utils/src/pfi.h                              |  244 ----
 ubi-utils/src/pfi2bin.c                          |  682 ----------
 ubi-utils/src/pfiflash.c                         |  264 ----
 ubi-utils/src/pfiflash.h                         |   76 --
 ubi-utils/src/pfiflash_error.h                   |   75 --
 ubi-utils/src/reader.c                           |  482 -------
 ubi-utils/src/reader.h                           |   87 --
 ubi-utils/src/ubiattach.c                        |  205 +++
 ubi-utils/src/ubicrc32.c                         |  124 ++
 ubi-utils/src/ubidetach.c                        |  181 +++
 ubi-utils/src/ubiformat.c                        |  780 +++++++++++
 ubi-utils/src/ubigen.c                           |  359 -----
 ubi-utils/src/ubigen.h                           |  149 ---
 ubi-utils/src/ubimirror.c                        |  213 ---
 ubi-utils/src/ubimirror.h                        |   66 -
 ubi-utils/src/ubimkvol.c                         |  313 +++++
 ubi-utils/src/ubinfo.c                           |  410 ++++++
 ubi-utils/src/ubinize.c                          |  612 +++++++++
 ubi-utils/src/ubirename.c                        |  141 ++
 ubi-utils/src/ubirmvol.c                         |  230 ++++
 ubi-utils/src/ubiupdatevol.c                     |  355 +++++
 ubi-utils/src/unubi.c                            | 1024 ---------------
 ubi-utils/src/unubi_analyze.c                    |  463 -------
 ubi-utils/src/unubi_analyze.h                    |   87 --
 ubi-utils/testcases.txt                          |    9 -
 190 files changed, 23892 insertions(+), 23947 deletions(-)
 create mode 100644 ubi-utils/LICENSE.libiniparser
 delete mode 100644 ubi-utils/README
 delete mode 100644 ubi-utils/UBI.TXT
 delete mode 100644 ubi-utils/doc/unubi.roff
 delete mode 100644 ubi-utils/inc/libubi.h
 create mode 100644 ubi-utils/include/libiniparser.h
 create mode 100644 ubi-utils/include/libmtd.h
 create mode 100644 ubi-utils/include/libscan.h
 create mode 100644 ubi-utils/include/libubi.h
 create mode 100644 ubi-utils/include/libubigen.h
 delete mode 100644 ubi-utils/lib/Makefile.am
 delete mode 100644 ubi-utils/new-utils/.gitignore
 delete mode 100644 ubi-utils/new-utils/LICENSE.libiniparser
 delete mode 100644 ubi-utils/new-utils/Makefile
 delete mode 100644 ubi-utils/new-utils/README
 delete mode 100644 ubi-utils/new-utils/include/libiniparser.h
 delete mode 100644 ubi-utils/new-utils/include/libmtd.h
 delete mode 100644 ubi-utils/new-utils/include/libscan.h
 delete mode 100644 ubi-utils/new-utils/include/libubi.h
 delete mode 100644 ubi-utils/new-utils/include/libubigen.h
 delete mode 100644 ubi-utils/new-utils/src/common.c
 delete mode 100644 ubi-utils/new-utils/src/common.h
 delete mode 100644 ubi-utils/new-utils/src/crc32.c
 delete mode 100644 ubi-utils/new-utils/src/crc32.h
 delete mode 100644 ubi-utils/new-utils/src/dictionary.c
 delete mode 100644 ubi-utils/new-utils/src/dictionary.h
 delete mode 100644 ubi-utils/new-utils/src/libiniparser.c
 delete mode 100644 ubi-utils/new-utils/src/libmtd.c
 delete mode 100644 ubi-utils/new-utils/src/libscan.c
 delete mode 100644 ubi-utils/new-utils/src/libubi.c
 delete mode 100644 ubi-utils/new-utils/src/libubi_int.h
 delete mode 100644 ubi-utils/new-utils/src/libubigen.c
 delete mode 100644 ubi-utils/new-utils/src/ubiattach.c
 delete mode 100644 ubi-utils/new-utils/src/ubicrc32.c
 delete mode 100644 ubi-utils/new-utils/src/ubidetach.c
 delete mode 100644 ubi-utils/new-utils/src/ubiformat.c
 delete mode 100644 ubi-utils/new-utils/src/ubimkvol.c
 delete mode 100644 ubi-utils/new-utils/src/ubinfo.c
 delete mode 100644 ubi-utils/new-utils/src/ubinize.c
 delete mode 100644 ubi-utils/new-utils/src/ubirename.c
 delete mode 100644 ubi-utils/new-utils/src/ubirmvol.c
 delete mode 100644 ubi-utils/new-utils/src/ubiupdatevol.c
 create mode 100644 ubi-utils/old-utils/.gitignore
 create mode 100644 ubi-utils/old-utils/Makefile
 create mode 100644 ubi-utils/old-utils/README
 create mode 100644 ubi-utils/old-utils/UBI.TXT
 create mode 100644 ubi-utils/old-utils/doc/unubi.roff
 create mode 100644 ubi-utils/old-utils/inc/libubi.h
 create mode 100644 ubi-utils/old-utils/lib/Makefile.am
 create mode 100644 ubi-utils/old-utils/perl/f128_nand_sample.cfg
 create mode 100644 ubi-utils/old-utils/perl/f64_nor_sample.cfg
 create mode 100755 ubi-utils/old-utils/perl/mkpfi
 create mode 100755 ubi-utils/old-utils/perl/ubicrc32.pl
 create mode 100644 ubi-utils/old-utils/scripts/Makefile
 create mode 100644 ubi-utils/old-utils/scripts/README
 create mode 100644 ubi-utils/old-utils/scripts/TODO
 create mode 100644 ubi-utils/old-utils/scripts/bin2nand2bin_test.sh
 create mode 100644 ubi-utils/old-utils/scripts/inject_biterror.pl
 create mode 100755 ubi-utils/old-utils/scripts/jffs2_test.sh
 create mode 100755 ubi-utils/old-utils/scripts/mkdevs.pl
 create mode 100644 ubi-utils/old-utils/scripts/pdd.txt
 create mode 100755 ubi-utils/old-utils/scripts/run_all.sh
 create mode 100644 ubi-utils/old-utils/scripts/test.cfg
 create mode 100755 ubi-utils/old-utils/scripts/ubi_jffs2_test.sh
 create mode 100755 ubi-utils/old-utils/scripts/ubi_test.sh
 create mode 100755 ubi-utils/old-utils/scripts/ubi_tools_test.sh
 create mode 100644 ubi-utils/old-utils/scripts/unubi_test.sh
 create mode 100644 ubi-utils/old-utils/src/bin2nand.c
 create mode 100644 ubi-utils/old-utils/src/bootenv.c
 create mode 100644 ubi-utils/old-utils/src/bootenv.h
 create mode 100644 ubi-utils/old-utils/src/config.h
 create mode 100644 ubi-utils/old-utils/src/crc32.c
 create mode 100644 ubi-utils/old-utils/src/crc32.h
 create mode 100644 ubi-utils/old-utils/src/eb_chain.c
 create mode 100644 ubi-utils/old-utils/src/error.c
 create mode 100644 ubi-utils/old-utils/src/error.h
 create mode 100644 ubi-utils/old-utils/src/example_ubi.h
 create mode 100644 ubi-utils/old-utils/src/hashmap.c
 create mode 100644 ubi-utils/old-utils/src/hashmap.h
 create mode 100644 ubi-utils/old-utils/src/libpfiflash.c
 create mode 100644 ubi-utils/old-utils/src/libubi.c
 create mode 100644 ubi-utils/old-utils/src/libubi_int.h
 create mode 100644 ubi-utils/old-utils/src/libubigen.c
 create mode 100644 ubi-utils/old-utils/src/libubimirror.c
 create mode 100644 ubi-utils/old-utils/src/list.c
 create mode 100644 ubi-utils/old-utils/src/list.h
 create mode 100644 ubi-utils/old-utils/src/mkbootenv.c
 create mode 100644 ubi-utils/old-utils/src/nand2bin.c
 create mode 100644 ubi-utils/old-utils/src/nandcorr.c
 create mode 100644 ubi-utils/old-utils/src/nandecc.c
 create mode 100644 ubi-utils/old-utils/src/nandecc.h
 create mode 100644 ubi-utils/old-utils/src/pddcustomize.c
 create mode 100644 ubi-utils/old-utils/src/peb.c
 create mode 100644 ubi-utils/old-utils/src/peb.h
 create mode 100644 ubi-utils/old-utils/src/pfi.c
 create mode 100644 ubi-utils/old-utils/src/pfi.h
 create mode 100644 ubi-utils/old-utils/src/pfi2bin.c
 create mode 100644 ubi-utils/old-utils/src/pfiflash.c
 create mode 100644 ubi-utils/old-utils/src/pfiflash.h
 create mode 100644 ubi-utils/old-utils/src/pfiflash_error.h
 create mode 100644 ubi-utils/old-utils/src/reader.c
 create mode 100644 ubi-utils/old-utils/src/reader.h
 create mode 100644 ubi-utils/old-utils/src/ubigen.c
 create mode 100644 ubi-utils/old-utils/src/ubigen.h
 create mode 100644 ubi-utils/old-utils/src/ubimirror.c
 create mode 100644 ubi-utils/old-utils/src/ubimirror.h
 create mode 100644 ubi-utils/old-utils/src/unubi.c
 create mode 100644 ubi-utils/old-utils/src/unubi_analyze.c
 create mode 100644 ubi-utils/old-utils/src/unubi_analyze.h
 create mode 100644 ubi-utils/old-utils/testcases.txt
 delete mode 100644 ubi-utils/perl/f128_nand_sample.cfg
 delete mode 100644 ubi-utils/perl/f64_nor_sample.cfg
 delete mode 100755 ubi-utils/perl/mkpfi
 delete mode 100755 ubi-utils/perl/ubicrc32.pl
 delete mode 100644 ubi-utils/scripts/Makefile
 delete mode 100644 ubi-utils/scripts/README
 delete mode 100644 ubi-utils/scripts/TODO
 delete mode 100644 ubi-utils/scripts/bin2nand2bin_test.sh
 delete mode 100644 ubi-utils/scripts/inject_biterror.pl
 delete mode 100755 ubi-utils/scripts/jffs2_test.sh
 delete mode 100755 ubi-utils/scripts/mkdevs.pl
 delete mode 100644 ubi-utils/scripts/pdd.txt
 delete mode 100755 ubi-utils/scripts/run_all.sh
 delete mode 100644 ubi-utils/scripts/test.cfg
 delete mode 100755 ubi-utils/scripts/ubi_jffs2_test.sh
 delete mode 100755 ubi-utils/scripts/ubi_test.sh
 delete mode 100755 ubi-utils/scripts/ubi_tools_test.sh
 delete mode 100644 ubi-utils/scripts/unubi_test.sh
 delete mode 100644 ubi-utils/src/bin2nand.c
 delete mode 100644 ubi-utils/src/bootenv.c
 delete mode 100644 ubi-utils/src/bootenv.h
 create mode 100644 ubi-utils/src/common.c
 create mode 100644 ubi-utils/src/common.h
 delete mode 100644 ubi-utils/src/config.h
 create mode 100644 ubi-utils/src/dictionary.c
 create mode 100644 ubi-utils/src/dictionary.h
 delete mode 100644 ubi-utils/src/eb_chain.c
 delete mode 100644 ubi-utils/src/error.c
 delete mode 100644 ubi-utils/src/error.h
 delete mode 100644 ubi-utils/src/example_ubi.h
 delete mode 100644 ubi-utils/src/hashmap.c
 delete mode 100644 ubi-utils/src/hashmap.h
 create mode 100644 ubi-utils/src/libiniparser.c
 create mode 100644 ubi-utils/src/libmtd.c
 delete mode 100644 ubi-utils/src/libpfiflash.c
 create mode 100644 ubi-utils/src/libscan.c
 delete mode 100644 ubi-utils/src/libubimirror.c
 delete mode 100644 ubi-utils/src/list.c
 delete mode 100644 ubi-utils/src/list.h
 delete mode 100644 ubi-utils/src/mkbootenv.c
 delete mode 100644 ubi-utils/src/nand2bin.c
 delete mode 100644 ubi-utils/src/nandcorr.c
 delete mode 100644 ubi-utils/src/nandecc.c
 delete mode 100644 ubi-utils/src/nandecc.h
 delete mode 100644 ubi-utils/src/pddcustomize.c
 delete mode 100644 ubi-utils/src/peb.c
 delete mode 100644 ubi-utils/src/peb.h
 delete mode 100644 ubi-utils/src/pfi.c
 delete mode 100644 ubi-utils/src/pfi.h
 delete mode 100644 ubi-utils/src/pfi2bin.c
 delete mode 100644 ubi-utils/src/pfiflash.c
 delete mode 100644 ubi-utils/src/pfiflash.h
 delete mode 100644 ubi-utils/src/pfiflash_error.h
 delete mode 100644 ubi-utils/src/reader.c
 delete mode 100644 ubi-utils/src/reader.h
 create mode 100644 ubi-utils/src/ubiattach.c
 create mode 100644 ubi-utils/src/ubicrc32.c
 create mode 100644 ubi-utils/src/ubidetach.c
 create mode 100644 ubi-utils/src/ubiformat.c
 delete mode 100644 ubi-utils/src/ubigen.c
 delete mode 100644 ubi-utils/src/ubigen.h
 delete mode 100644 ubi-utils/src/ubimirror.c
 delete mode 100644 ubi-utils/src/ubimirror.h
 create mode 100644 ubi-utils/src/ubimkvol.c
 create mode 100644 ubi-utils/src/ubinfo.c
 create mode 100644 ubi-utils/src/ubinize.c
 create mode 100644 ubi-utils/src/ubirename.c
 create mode 100644 ubi-utils/src/ubirmvol.c
 create mode 100644 ubi-utils/src/ubiupdatevol.c
 delete mode 100644 ubi-utils/src/unubi.c
 delete mode 100644 ubi-utils/src/unubi_analyze.c
 delete mode 100644 ubi-utils/src/unubi_analyze.h
 delete mode 100644 ubi-utils/testcases.txt

diff --git a/ubi-utils/.gitignore b/ubi-utils/.gitignore
index 83e8b71..4155cd1 100644
--- a/ubi-utils/.gitignore
+++ b/ubi-utils/.gitignore
@@ -1,9 +1,10 @@
-/bin2nand
-/mkbootenv
-/nand2bin
-/pddcustomize
-/pfi2bin
-/pfiflash
-/ubigen
-/ubimirror
-/unubi
+/ubiattach
+/ubicrc32
+/ubidetach
+/ubiformat
+/ubimkvol
+/ubinfo
+/ubinize
+/ubirename
+/ubirmvol
+/ubiupdatevol
diff --git a/ubi-utils/LICENSE.libiniparser b/ubi-utils/LICENSE.libiniparser
new file mode 100644
index 0000000..dbfa45d
--- /dev/null
+++ b/ubi-utils/LICENSE.libiniparser
@@ -0,0 +1,21 @@
+Copyright (c) 2000-2007 by Nicolas Devillard.
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile
index 3be813a..020fe09 100644
--- a/ubi-utils/Makefile
+++ b/ubi-utils/Makefile
@@ -4,58 +4,56 @@
 
 KERNELHDR := ../include
 
-CFLAGS ?= -O2 -g -Werror
-CPPFLAGS += -I./inc -I./src -I$(KERNELHDR) \
-	-std=gnu99 -DPACKAGE_VERSION=\"1.0\"
+SUBDIRS = old-utils
 
-PERLPROGS = mkpfi ubicrc32.pl
+#CFLAGS += -Werror
+CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR)
 
-SUBDIRS = new-utils
+LIBS = libubi libmtd libubigen libiniparser libscan
+TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
+          ubidetach ubinize ubiformat ubirename
 
-TARGETS = pfiflash pddcustomize ubimirror bin2nand nand2bin ubigen \
-	mkbootenv unubi pfi2bin
-
-vpath   %.c ./src
+vpath %.c src
 
 include ../common.mk
 
-$(BUILDDIR)/pddcustomize: $(addprefix $(BUILDDIR)/,\
-	pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \
-	libubi.o crc32.o)
+# And the below is the rule to get final executable from its .o and common.o
+$(TARGETS): $(addprefix $(BUILDDIR)/,\
+	libubi.a common.o)
+#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@
+
+$(BUILDDIR)/ubicrc32: $(addprefix $(BUILDDIR)/,\
+	ubicrc32.o crc32.o)
+#	$(CC) $(CFLAGS) -o $@ $^
 
-$(BUILDDIR)/pfiflash: $(addprefix $(BUILDDIR)/,\
-	pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \
-	bootenv.o hashmap.o pfi.o libubi.o crc32.o)
+$(BUILDDIR)/ubinize: $(addprefix $(BUILDDIR)/,\
+	ubinize.o common.o crc32.o libiniparser.a libubigen.a)
+#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@
 
-$(BUILDDIR)/ubimirror: $(addprefix $(BUILDDIR)/,\
-	ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \
-	libubi.o crc32.o)
+$(BUILDDIR)/ubiformat: $(addprefix $(BUILDDIR)/,\
+	ubiformat.o common.o crc32.o libmtd.a libscan.a libubi.a libubigen.a)
+#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@
 
-$(BUILDDIR)/nand2bin: $(addprefix $(BUILDDIR)/,\
-	nand2bin.o nandecc.o nandcorr.o)
+$(BUILDDIR)/libubi.a: $(BUILDDIR)/libubi.o
 
-$(BUILDDIR)/bin2nand: $(addprefix $(BUILDDIR)/,\
-	bin2nand.o error.o nandecc.o)
+$(BUILDDIR)/libmtd.a: $(BUILDDIR)/libmtd.o
 
-$(BUILDDIR)/ubigen: $(addprefix $(BUILDDIR)/,\
-	ubigen.o libubigen.o crc32.o)
+$(BUILDDIR)/libubigen.a: $(BUILDDIR)/libubigen.o
 
-$(BUILDDIR)/mkbootenv: $(addprefix $(BUILDDIR)/,\
-	mkbootenv.o bootenv.o hashmap.o error.o crc32.o)
+$(BUILDDIR)/libiniparser.a: $(addprefix $(BUILDDIR)/,\
+	libiniparser.o dictionary.o)
 
-$(BUILDDIR)/unubi: $(addprefix $(BUILDDIR)/,\
-	unubi.o crc32.o unubi_analyze.o eb_chain.o)
+$(BUILDDIR)/libscan.a: $(addprefix $(BUILDDIR)/,\
+	libscan.o crc32.o)
 
-$(BUILDDIR)/pfi2bin: $(addprefix $(BUILDDIR)/,\
-	pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \
-	hashmap.o reader.o pfi.o)
+clean::
+	rm -f $(addsuffix .a, $(LIBS))
 
 install::
 	mkdir -p ${DESTDIR}/${SBINDIR}
 	install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
-	(cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/)
 
 uninstall:
-	for file in ${TARGETS} ${PERLPROGS}; do \
+	for file in ${TARGETS}; do \
 		$(RM) ${DESTDIR}/${SBINDIR}/$$file; \
 	done
diff --git a/ubi-utils/README b/ubi-utils/README
deleted file mode 100644
index d976a76..0000000
--- a/ubi-utils/README
+++ /dev/null
@@ -1,236 +0,0 @@
-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/UBI.TXT b/ubi-utils/UBI.TXT
deleted file mode 100644
index 9a1c3c7..0000000
--- a/ubi-utils/UBI.TXT
+++ /dev/null
@@ -1,108 +0,0 @@
-UBI - Unsorted Block Images
-
-UBI (Latin: "where?") manages multiple logical volumes on a single
-flash device, specifically supporting NAND flash devices. UBI provides
-a flexible partitioning concept which still allows for wear-levelling
-across the whole flash device.
-
-In a sense, UBI may be compared to the Logical Volume Manager
-(LVM). Whereas LVM maps logical sector numbers to physical HDD sector
-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: 
-http://www.linux-mtd.infradead.org/doc/ubi.html
-
-Partitioning/Re-partitioning
-
-  An UBI volume occupies a certain number of erase blocks. This is
-  limited by a configured maximum volume size, which could also be
-  viewed as the partition size. Each individual UBI volume's size can
-  be changed independently of the other UBI volumes, provided that the
-  sum of all volume sizes doesn't exceed a certain limit.
-
-  UBI supports dynamic volumes and static volumes. Static volumes are
-  read-only and their contents are protected by CRC check sums.
-
-Bad eraseblocks handling
-
-  UBI transparently handles bad eraseblocks. When a physical
-  eraseblock becomes bad, it is substituted by a good physical
-  eraseblock, and the user does not even notice this.
-
-Scrubbing
-
-  On a NAND flash bit flips can occur on any write operation,
-  sometimes also on read. If bit flips persist on the device, at first
-  they can still be corrected by ECC, but once they accumulate,
-  correction will become impossible. Thus it is best to actively scrub
-  the affected eraseblock, by first copying it to a free eraseblock
-  and then erasing the original. The UBI layer performs this type of
-  scrubbing under the covers, transparently to the UBI volume users.
-
-Erase Counts
-
-  UBI maintains an erase count header per eraseblock. This frees
-  higher-level layers (like file systems) from doing this and allows
-  for centralized erase count management instead. The erase counts are
-  used by the wear-levelling algorithm in the UBI layer. The algorithm
-  itself is exchangeable.
-
-Booting from NAND
-
-  For booting directly from NAND flash the hardware must at least be
-  capable of fetching and executing a small portion of the NAND
-  flash. Some NAND flash controllers have this kind of support. They
-  usually limit the window to a few kilobytes in erase block 0. This
-  "initial program loader" (IPL) must then contain sufficient logic to
-  load and execute the next boot phase.
-
-  Due to bad eraseblocks, which may be randomly scattered over the
-  flash device, it is problematic to store the "secondary program
-  loader" (SPL) statically. Also, due to bit-flips it may become
-  corrupted over time. UBI allows to solve this problem gracefully by
-  storing the SPL in a small static UBI volume.
-
-UBI volumes vs. static partitions
-
-  UBI volumes are still very similar to static MTD partitions:
-
-    * both consist of eraseblocks (logical eraseblocks in case of UBI
-      volumes, and physical eraseblocks in case of static partitions;
-    * both support three basic operations - read, write, erase.
-
-  But UBI volumes have the following advantages over traditional
-  static MTD partitions:
-
-    * there are no eraseblock wear-leveling constraints in case of UBI
-      volumes, so the user should not care about this;
-    * there are no bit-flips and bad eraseblocks in case of UBI volumes.
-
-  So, UBI volumes may be considered as flash devices with relaxed
-  restrictions.
-
-Where can it be found?
-
-  Documentation, kernel code and applications can be found in the MTD
-  gits. 
-
-What are the applications for?
-
-  The applications help to create binary flash images for two
-  purposes: pfi files (partial flash images) for in-system update of
-  UBI volumes, and plain binary images, with or without OOB data in
-  case of NAND, for a manufacturing step. Furthermore some tools
-  are/and will be created that allow flash content analysis after a
-  system has crashed.
-
-Who did UBI?
-
-  The original ideas, where UBI is based on, were developed by Andreas
-  Arnez, Frank Haverkamp and Thomas Gleixner. Josh W. Boyer and
-  some others were involved too. The implementation of the kernel
-  layer was done by Artem B. Bityutskiy. The user-space applications
-  and tools were written by Oliver Lohmann with contributions from
-  Frank Haverkamp, Andreas Arnez, and Artem. Joern Engel contributed a
-  patch which modifies JFFS2 so that it can be run on a UBI
-  volume. Thomas Gleixner did modifications to the NAND layer and also
-  some to JFFS2 to make it work.
diff --git a/ubi-utils/doc/unubi.roff b/ubi-utils/doc/unubi.roff
deleted file mode 100644
index 6cebc46..0000000
--- a/ubi-utils/doc/unubi.roff
+++ /dev/null
@@ -1,123 +0,0 @@
-.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
deleted file mode 100644
index 82824bd..0000000
--- a/ubi-utils/inc/libubi.h
+++ /dev/null
@@ -1,268 +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-media.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/include/libiniparser.h b/ubi-utils/include/libiniparser.h
new file mode 100644
index 0000000..be3c667
--- /dev/null
+++ b/ubi-utils/include/libiniparser.h
@@ -0,0 +1,280 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+   @file    iniparser.h
+   @author  N. Devillard
+   @date    Sep 2007
+   @version 3.0
+   @brief   Parser for ini files.
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+	$Id: iniparser.h,v 1.24 2007-11-23 21:38:19 ndevilla Exp $
+	$Revision: 1.24 $
+*/
+
+#ifndef _INIPARSER_H_
+#define _INIPARSER_H_
+
+/*---------------------------------------------------------------------------
+   								Includes
+ ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * The following #include is necessary on many Unixes but not Linux.
+ * It is not needed for Windows platforms.
+ * Uncomment it if needed.
+ */
+/* #include <unistd.h> */
+
+#include "dictionary.h"
+
+/*---------------------------------------------------------------------------
+   								Macros
+ ---------------------------------------------------------------------------*/
+/** For backwards compatibility only */
+#define iniparser_getstr(d, k)  iniparser_getstring(d, k, NULL)
+#define iniparser_setstr        iniparser_setstring
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get number of sections in a dictionary
+  @param    d   Dictionary to examine
+  @return   int Number of sections found in dictionary
+
+  This function returns the number of sections found in a dictionary.
+  The test to recognize sections is done on the string stored in the
+  dictionary: a section name is given as "section" whereas a key is
+  stored as "section:key", thus the test looks for entries that do not
+  contain a colon.
+
+  This clearly fails in the case a section name contains a colon, but
+  this should simply be avoided.
+
+  This function returns -1 in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+
+int iniparser_getnsec(dictionary * d);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get name for section n in a dictionary.
+  @param    d   Dictionary to examine
+  @param    n   Section number (from 0 to nsec-1).
+  @return   Pointer to char string
+
+  This function locates the n-th section in a dictionary and returns
+  its name as a pointer to a string statically allocated inside the
+  dictionary. Do not free or modify the returned string!
+
+  This function returns NULL in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+
+char * iniparser_getsecname(dictionary * d, int n);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Save a dictionary to a loadable ini file
+  @param    d   Dictionary to dump
+  @param    f   Opened file pointer to dump to
+  @return   void
+
+  This function dumps a given dictionary into a loadable ini file.
+  It is Ok to specify @c stderr or @c stdout as output files.
+ */
+/*--------------------------------------------------------------------------*/
+
+void iniparser_dump_ini(dictionary * d, FILE * f);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Dump a dictionary to an opened file pointer.
+  @param    d   Dictionary to dump.
+  @param    f   Opened file pointer to dump to.
+  @return   void
+
+  This function prints out the contents of a dictionary, one element by
+  line, onto the provided file pointer. It is OK to specify @c stderr
+  or @c stdout as output files. This function is meant for debugging
+  purposes mostly.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_dump(dictionary * d, FILE * f);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key
+  @param    d       Dictionary to search
+  @param    key     Key string to look for
+  @param    def     Default value to return if key not found.
+  @return   pointer to statically allocated character string
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the pointer passed as 'def' is returned.
+  The returned char pointer is pointing to a string allocated in
+  the dictionary, do not free or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getstring(dictionary * d, const char * key, char * def);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key, convert to an int
+  @param    d Dictionary to search
+  @param    key Key string to look for
+  @param    notfound Value to return in case of error
+  @return   integer
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the notfound value is returned.
+
+  Supported values for integers include the usual C notation
+  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
+  are supported. Examples:
+
+  - "42"      ->  42
+  - "042"     ->  34 (octal -> decimal)
+  - "0x42"    ->  66 (hexa  -> decimal)
+
+  Warning: the conversion may overflow in various ways. Conversion is
+  totally outsourced to strtol(), see the associated man page for overflow
+  handling.
+
+  Credits: Thanks to A. Becker for suggesting strtol()
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getint(dictionary * d, const char * key, int notfound);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key, convert to a double
+  @param    d Dictionary to search
+  @param    key Key string to look for
+  @param    notfound Value to return in case of error
+  @return   double
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the notfound value is returned.
+ */
+/*--------------------------------------------------------------------------*/
+double iniparser_getdouble(dictionary * d, char * key, double notfound);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key, convert to a boolean
+  @param    d Dictionary to search
+  @param    key Key string to look for
+  @param    notfound Value to return in case of error
+  @return   integer
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the notfound value is returned.
+
+  A true boolean is found if one of the following is matched:
+
+  - A string starting with 'y'
+  - A string starting with 'Y'
+  - A string starting with 't'
+  - A string starting with 'T'
+  - A string starting with '1'
+
+  A false boolean is found if one of the following is matched:
+
+  - A string starting with 'n'
+  - A string starting with 'N'
+  - A string starting with 'f'
+  - A string starting with 'F'
+  - A string starting with '0'
+
+  The notfound value returned if no boolean is identified, does not
+  necessarily have to be 0 or 1.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getboolean(dictionary * d, const char * key, int notfound);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Set an entry in a dictionary.
+  @param    ini     Dictionary to modify.
+  @param    entry   Entry to modify (entry name)
+  @param    val     New value to associate to the entry.
+  @return   int 0 if Ok, -1 otherwise.
+
+  If the given entry can be found in the dictionary, it is modified to
+  contain the provided value. If it cannot be found, -1 is returned.
+  It is Ok to set val to NULL.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_setstring(dictionary * ini, char * entry, char * val);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Delete an entry in a dictionary
+  @param    ini     Dictionary to modify
+  @param    entry   Entry to delete (entry name)
+  @return   void
+
+  If the given entry can be found, it is deleted from the dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_unset(dictionary * ini, char * entry);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Finds out if a given entry exists in a dictionary
+  @param    ini     Dictionary to search
+  @param    entry   Name of the entry to look for
+  @return   integer 1 if entry exists, 0 otherwise
+
+  Finds out if a given entry exists in the dictionary. Since sections
+  are stored as keys with NULL associated values, this is the only way
+  of querying for the presence of sections in a dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_find_entry(dictionary * ini, char * entry) ;
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Parse an ini file and return an allocated dictionary object
+  @param    ininame Name of the ini file to read.
+  @return   Pointer to newly allocated dictionary
+
+  This is the parser for ini files. This function is called, providing
+  the name of the file to be read. It returns a dictionary object that
+  should not be accessed directly, but through accessor functions
+  instead.
+
+  The returned dictionary must be freed using iniparser_freedict().
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * iniparser_load(const char * ininame);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Free all memory associated to an ini dictionary
+  @param    d Dictionary to free
+  @return   void
+
+  Free all memory associated to an ini dictionary.
+  It is mandatory to call this function before the dictionary object
+  gets out of the current context.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_freedict(dictionary * d);
+
+#endif
diff --git a/ubi-utils/include/libmtd.h b/ubi-utils/include/libmtd.h
new file mode 100644
index 0000000..d3c6a63
--- /dev/null
+++ b/ubi-utils/include/libmtd.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * MTD library.
+ */
+
+#ifndef __LIBMTD_H__
+#define __LIBMTD_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * struct mtd_info - information about an MTD device.
+ * @num: MTD device number
+ * @major: major number of corresponding character device
+ * @minor: minor number of corresponding character device
+ * @type: flash type (constants like %MTD_NANDFLASH defined in mtd-abi.h)
+ * @type_str: static R/O flash type string
+ * @size: device size in bytes
+ * @eb_cnt: count of eraseblocks
+ * @eb_size: eraseblock size
+ * @min_io_size: minimum input/output unit size
+ * @subpage_size: sub-page size (not set by 'mtd_get_info()'!!!)
+ * @rdonly: non-zero if the device is read-only
+ * @allows_bb: non-zero if the MTD device may have bad eraseblocks
+ * @fd: descriptor of the opened MTD character device node
+ */
+struct mtd_info
+{
+	int num;
+	int major;
+	int minor;
+	int type;
+	const char *type_str;
+	long long size;
+	int eb_cnt;
+	int eb_size;
+	int min_io_size;
+	int subpage_size;
+	unsigned int rdonly:1;
+	unsigned int allows_bb:1;
+	int fd;
+};
+
+int mtd_get_info(const char *node, struct mtd_info *mtd);
+int mtd_erase(const struct mtd_info *mtd, int eb);
+int mtd_is_bad(const struct mtd_info *mtd, int eb);
+int mtd_read(const struct mtd_info *mtd, int eb, int offs, void *buf, int len);
+int mtd_write(const struct mtd_info *mtd, int eb, int offs, void *buf, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIBMTD_H__ */
diff --git a/ubi-utils/include/libscan.h b/ubi-utils/include/libscan.h
new file mode 100644
index 0000000..5afc93e
--- /dev/null
+++ b/ubi-utils/include/libscan.h
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * UBI scanning library.
+ */
+
+#ifndef __LIBSCAN_H__
+#define __LIBSCAN_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * If an eraseblock does not contain an erase counter, this value is used
+ * instead of the erase counter.
+ */
+#define NO_EC 0xFFFFFFFF
+
+/*
+ * If an eraseblock contains a corrupted erase counter, this value is used
+ * instead of the erase counter.
+ */
+#define CORRUPT_EC 0xFFFFFFFE
+
+/*
+ * If an eraseblock does not contain an erase counter, one of these values is
+ * used.
+ *
+ * @EB_EMPTY: the eraseblock appeared to be empty
+ * @EB_CORRUPTED: the eraseblock contains corrupted erase counter header
+ * @EB_ALIEN: the eraseblock contains some non-UBI data
+ * @EC_MAX: maximum allowed erase counter value
+ */
+enum
+{
+	EB_EMPTY     = 0xFFFFFFFF,
+	EB_CORRUPTED = 0xFFFFFFFE,
+	EB_ALIEN     = 0xFFFFFFFD,
+	EB_BAD       = 0xFFFFFFFC,
+	EC_MAX       = UBI_MAX_ERASECOUNTER,
+};
+
+/**
+ * struct ubi_scan_info - UBI scanning information.
+ * @ec: erase counters or eraseblock status for all eraseblocks
+ * @mean_ec: mean erase counter
+ * @ok_cnt: count of eraseblock with correct erase counter header
+ * @empty_cnt: count of supposedly eraseblocks
+ * @corrupted_cnt: count of eraseblocks with corrupted erase counter header
+ * @alien_cnt: count of eraseblock containing non-ubi data
+ * @bad_cnt: count of bad eraseblocks
+ * @bad_cnt: count of non-bad eraseblocks
+ * @vid_hdr_offs: volume ID header offset from the found EC headers (%-1 means
+ *                undefined)
+ * @data_offs: data offset from the found EC headers (%-1 means undefined)
+ */
+struct ubi_scan_info
+{
+	uint32_t *ec;
+	long long mean_ec;
+	int ok_cnt;
+	int empty_cnt;
+	int corrupted_cnt;
+	int alien_cnt;
+	int bad_cnt;
+	int good_cnt;
+	int vid_hdr_offs;
+	int data_offs;
+};
+
+struct mtd_info;
+
+/**
+ * ubi_scan - scan an MTD device.
+ * @mtd: information about the MTD device to scan
+ * @info: the result of the scanning is returned here
+ * @verbose: verbose mode: %0 - be silent, %1 - output progress information,
+ *           2 - debugging output mode
+ */
+int ubi_scan(struct mtd_info *mtd, struct ubi_scan_info **info, int verbose);
+
+/**
+ * ubi_scan_free - free scanning information.
+ * @si: scanning information to free
+ */
+void ubi_scan_free(struct ubi_scan_info *si);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIBSCAN_H__ */
+
diff --git a/ubi-utils/include/libubi.h b/ubi-utils/include/libubi.h
new file mode 100644
index 0000000..1299e81
--- /dev/null
+++ b/ubi-utils/include/libubi.h
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * UBI (Unsorted Block Images) library.
+ */
+
+#ifndef __LIBUBI_H__
+#define __LIBUBI_H__
+
+#include <ctype.h>
+#include <stdint.h>
+#include <mtd/ubi-user.h>
+#include <mtd/ubi-media.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_id: lowest volume ID
+ * @highest_vol_id: highest volume ID
+ * @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_id;
+	int highest_vol_id;
+	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.
+ * @required: if non-zero, libubi will print an error messages if this UBI is
+ *            not present in the system
+ *
+ * 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(int required);
+
+/**
+ * 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);
+
+/**
+ * mtd_num2ubi_dev - find UBI device by attached MTD device.
+ * @@desc: UBI library descriptor
+ * @mtd_num: MTD device number
+ * @dev_num: UBI device number is returned here
+ *
+ * This function finds UBI device to which MTD device @mtd_num is attached.
+ * Returns %0 if the UBI device was found and %-1 if not.
+ */
+int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num);
+
+/**
+ * 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_rnvols - rename UBI volumes.
+ * @desc: UBI library descriptor
+ * @node: name of the UBI character device to remove a volume from
+ * @rnvol: description of volumes to rename
+ *
+ * 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_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol);
+
+/**
+ * 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 ID, 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_get_vol_info1_nm - get UBI volume information by volume name.
+ * @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 name, not UBI volume ID.
+ */
+int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name,
+			 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. The caller is assumed to write @bytes data to the
+ * volume @fd afterwards.
+ */
+int ubi_update_start(libubi_t desc, int fd, long long bytes);
+
+/**
+ * ubi_leb_change_start - start atomic LEB change.
+ * @desc: UBI library descriptor
+ * @fd: volume character devie file descriptor
+ * @lnum: LEB number to change
+ * @bytes: how many bytes of new data will be written to the LEB
+ * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
+ *
+ * This function initiates atomic LEB change operation and returns %0 in case
+ * of success and %-1 in case of error. he caller is assumed to write @bytes
+ * data to the volume @fd afterwards.
+ */
+int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__LIBUBI_H__ */
diff --git a/ubi-utils/include/libubigen.h b/ubi-utils/include/libubigen.h
new file mode 100644
index 0000000..c2b95b0
--- /dev/null
+++ b/ubi-utils/include/libubigen.h
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+/*
+ * Authors: Frank Haverkamp
+ *          Artem Bityutskiy
+ */
+
+#ifndef __LIBUBIGEN_H__
+#define __LIBUBIGEN_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * struct ubigen_info - libubigen information.
+ * @leb_size: logical eraseblock size
+ * @peb_size: size of the physical eraseblock
+ * @min_io_size: minimum input/output unit size
+ * @vid_hdr_offs: offset of the VID header
+ * @data_offs: data offset
+ * @ubi_ver: UBI version
+ * @vtbl_size: volume table size
+ * @max_volumes: maximum amount of volumes
+ */
+struct ubigen_info
+{
+	int leb_size;
+	int peb_size;
+	int min_io_size;
+	int vid_hdr_offs;
+	int data_offs;
+	int ubi_ver;
+	int vtbl_size;
+	int max_volumes;
+};
+
+/**
+ * struct ubigen_vol_info - information about a volume.
+ * @id: volume id
+ * @type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
+ * @alignment: volume alignment
+ * @data_pad: how many bytes are unused at the end of the each physical
+ *            eraseblock to satisfy the requested alignment
+ * @usable_leb_size: LEB size accessible for volume users
+ * @name: volume name
+ * @name_len: volume name length
+ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
+ *          %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+ * @used_ebs: total number of used logical eraseblocks in this volume (relevant
+ *            for static volumes only)
+ * @bytes: size of the volume contents in bytes (relevant for static volumes
+ *         only)
+ * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
+ */
+struct ubigen_vol_info
+{
+	int id;
+	int type;
+	int alignment;
+	int data_pad;
+	int usable_leb_size;
+	const char *name;
+	int name_len;
+	int compat;
+	int used_ebs;
+	long long bytes;
+	uint8_t flags;
+};
+
+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);
+struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui);
+void ubigen_init_ec_hdr(const struct ubigen_info *ui,
+		        struct ubi_ec_hdr *hdr, long long ec);
+int ubigen_get_vtbl_size(const struct ubigen_info *ui);
+int ubigen_add_volume(const struct ubigen_info *ui,
+		      const struct ubigen_vol_info *vi,
+		      struct ubi_vtbl_record *vtbl);
+int ubigen_write_volume(const struct ubigen_info *ui,
+			const struct ubigen_vol_info *vi, long long ec,
+			long long bytes, int in, int out);
+int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
+			    long long ec1, long long ec2,
+			    struct ubi_vtbl_record *vtbl, int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__LIBUBIGEN_H__ */
diff --git a/ubi-utils/lib/Makefile.am b/ubi-utils/lib/Makefile.am
deleted file mode 100644
index 1b0dc01..0000000
--- a/ubi-utils/lib/Makefile.am
+++ /dev/null
@@ -1,58 +0,0 @@
-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/new-utils/.gitignore b/ubi-utils/new-utils/.gitignore
deleted file mode 100644
index 4155cd1..0000000
--- a/ubi-utils/new-utils/.gitignore
+++ /dev/null
@@ -1,10 +0,0 @@
-/ubiattach
-/ubicrc32
-/ubidetach
-/ubiformat
-/ubimkvol
-/ubinfo
-/ubinize
-/ubirename
-/ubirmvol
-/ubiupdatevol
diff --git a/ubi-utils/new-utils/LICENSE.libiniparser b/ubi-utils/new-utils/LICENSE.libiniparser
deleted file mode 100644
index dbfa45d..0000000
--- a/ubi-utils/new-utils/LICENSE.libiniparser
+++ /dev/null
@@ -1,21 +0,0 @@
-Copyright (c) 2000-2007 by Nicolas Devillard.
-MIT License
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
diff --git a/ubi-utils/new-utils/Makefile b/ubi-utils/new-utils/Makefile
deleted file mode 100644
index 83751e6..0000000
--- a/ubi-utils/new-utils/Makefile
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Makefile for ubi-utils
-#
-
-KERNELHDR := ../../include
-
-#CFLAGS += -Werror
-CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR)
-
-LIBS = libubi libmtd libubigen libiniparser libscan
-TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
-          ubidetach ubinize ubiformat ubirename
-
-vpath %.c src
-
-include ../../common.mk
-
-# And the below is the rule to get final executable from its .o and common.o
-$(TARGETS): $(addprefix $(BUILDDIR)/,\
-	libubi.a common.o)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@
-
-$(BUILDDIR)/ubicrc32: $(addprefix $(BUILDDIR)/,\
-	ubicrc32.o crc32.o)
-#	$(CC) $(CFLAGS) -o $@ $^
-
-$(BUILDDIR)/ubinize: $(addprefix $(BUILDDIR)/,\
-	ubinize.o common.o crc32.o libiniparser.a libubigen.a)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@
-
-$(BUILDDIR)/ubiformat: $(addprefix $(BUILDDIR)/,\
-	ubiformat.o common.o crc32.o libmtd.a libscan.a libubi.a libubigen.a)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@
-
-$(BUILDDIR)/libubi.a: $(BUILDDIR)/libubi.o
-
-$(BUILDDIR)/libmtd.a: $(BUILDDIR)/libmtd.o
-
-$(BUILDDIR)/libubigen.a: $(BUILDDIR)/libubigen.o
-
-$(BUILDDIR)/libiniparser.a: $(addprefix $(BUILDDIR)/,\
-	libiniparser.o dictionary.o)
-
-$(BUILDDIR)/libscan.a: $(addprefix $(BUILDDIR)/,\
-	libscan.o crc32.o)
-
-clean::
-	rm -f $(addsuffix .a, $(LIBS))
-
-install::
-	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
-
-uninstall:
-	for file in ${TARGETS}; do \
-		$(RM) ${DESTDIR}/${SBINDIR}/$$file; \
-	done
diff --git a/ubi-utils/new-utils/README b/ubi-utils/new-utils/README
deleted file mode 100644
index 41c5957..0000000
--- a/ubi-utils/new-utils/README
+++ /dev/null
@@ -1,55 +0,0 @@
-This directory contains a new UBI toolchain which is intended to replace
-the old one. All utilities support "-h" option which prints sufficient
-usage information. See the MTD web-site for more information.
-
-Motivation for new tool-chain.
-
-I was doing very active UBI development and had to add new features like
-dynamic UBI devices and auto-resize feature. Because of the mess in the
-the old tools I basically could not figure out how to upgrade them. In
-my humble oppinion, they are unmaintainable. The original authors did not
-show enthusiasm when I mailed them and asked to clean-up the tool-chain
-[1]. Thus, I re-implemented them, but I did borrow things from the old
-tool-chain and preserved copyrights and author names.
-
-I really did try to clean-up the old tool chain, but gave up (see git
-history for confirmation). So,
-
-1. I found the source codes very difficult to navigate and read, especially
-   those related to pdd, pfi, and bootenv. Try to do this yourself - they
-   are a puzzle.
-2. I foud the concept of PFI needlesly complecated - PFI file is nothing
-   else but the initial configuration .ini file + the contents of the
-   UBI volumes packed into one file, but with some changes of the .ini file's
-   format. The PFI file format is not very nice and it is difficult to parse,
-   especially because the PFI headers do not tell you data star and end for
-   each data chunk, and you have to do additional parsing.
-
-   So basically, you have .ini file + images, then you transfer this to pfi,
-   which does not add any other information. For .ini you have libraries
-   which may parse them, for pfi - not. Then you have to parse this pfi
-   which adds unneeded and complex code. This all needs lists, hashmaps,
-   and so on - for no reason.
-3. I found the command line options of the utilities to be inconsistent.
-   This is OK when you script your single task and do not touch it anymore.
-   But when you have to use the utilities while developing and testing,
-   It is difficult to remember their inconsistent options.
-4. I found it wrong to add development options to user utilities like
-   "broken update". End users should not see them.
-5. I did not find any consistent style and convention inside which
-   irritated me.
-6. I found it weird to introduce needless "logging infrastructure" instead
-   of just re-directing stdout and stderr to another file.
-7. I found the tool to be rather IBM-setup oriented. For example, the VID
-   header position was hard-coded. Some utilities were just weird, like
-   mkbootenv, which changed some ethernet addresses mentioned in a
-   configuration file.
-8. Finally, it was very difficult to realize what is pfi and pdd, what for,
-   why I need this transiant pfi file when I just want to create an UBI
-   image. There was zero documentation.
-
-And so on.
-
-Feb 19, 2008, Artem Bityutskiy.
-
-[1]. http://lists.infradead.org/pipermail/linux-mtd/2007-December/020134.html
diff --git a/ubi-utils/new-utils/include/libiniparser.h b/ubi-utils/new-utils/include/libiniparser.h
deleted file mode 100644
index be3c667..0000000
--- a/ubi-utils/new-utils/include/libiniparser.h
+++ /dev/null
@@ -1,280 +0,0 @@
-
-/*-------------------------------------------------------------------------*/
-/**
-   @file    iniparser.h
-   @author  N. Devillard
-   @date    Sep 2007
-   @version 3.0
-   @brief   Parser for ini files.
-*/
-/*--------------------------------------------------------------------------*/
-
-/*
-	$Id: iniparser.h,v 1.24 2007-11-23 21:38:19 ndevilla Exp $
-	$Revision: 1.24 $
-*/
-
-#ifndef _INIPARSER_H_
-#define _INIPARSER_H_
-
-/*---------------------------------------------------------------------------
-   								Includes
- ---------------------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * The following #include is necessary on many Unixes but not Linux.
- * It is not needed for Windows platforms.
- * Uncomment it if needed.
- */
-/* #include <unistd.h> */
-
-#include "dictionary.h"
-
-/*---------------------------------------------------------------------------
-   								Macros
- ---------------------------------------------------------------------------*/
-/** For backwards compatibility only */
-#define iniparser_getstr(d, k)  iniparser_getstring(d, k, NULL)
-#define iniparser_setstr        iniparser_setstring
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get number of sections in a dictionary
-  @param    d   Dictionary to examine
-  @return   int Number of sections found in dictionary
-
-  This function returns the number of sections found in a dictionary.
-  The test to recognize sections is done on the string stored in the
-  dictionary: a section name is given as "section" whereas a key is
-  stored as "section:key", thus the test looks for entries that do not
-  contain a colon.
-
-  This clearly fails in the case a section name contains a colon, but
-  this should simply be avoided.
-
-  This function returns -1 in case of error.
- */
-/*--------------------------------------------------------------------------*/
-
-int iniparser_getnsec(dictionary * d);
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get name for section n in a dictionary.
-  @param    d   Dictionary to examine
-  @param    n   Section number (from 0 to nsec-1).
-  @return   Pointer to char string
-
-  This function locates the n-th section in a dictionary and returns
-  its name as a pointer to a string statically allocated inside the
-  dictionary. Do not free or modify the returned string!
-
-  This function returns NULL in case of error.
- */
-/*--------------------------------------------------------------------------*/
-
-char * iniparser_getsecname(dictionary * d, int n);
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Save a dictionary to a loadable ini file
-  @param    d   Dictionary to dump
-  @param    f   Opened file pointer to dump to
-  @return   void
-
-  This function dumps a given dictionary into a loadable ini file.
-  It is Ok to specify @c stderr or @c stdout as output files.
- */
-/*--------------------------------------------------------------------------*/
-
-void iniparser_dump_ini(dictionary * d, FILE * f);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Dump a dictionary to an opened file pointer.
-  @param    d   Dictionary to dump.
-  @param    f   Opened file pointer to dump to.
-  @return   void
-
-  This function prints out the contents of a dictionary, one element by
-  line, onto the provided file pointer. It is OK to specify @c stderr
-  or @c stdout as output files. This function is meant for debugging
-  purposes mostly.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_dump(dictionary * d, FILE * f);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key
-  @param    d       Dictionary to search
-  @param    key     Key string to look for
-  @param    def     Default value to return if key not found.
-  @return   pointer to statically allocated character string
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the pointer passed as 'def' is returned.
-  The returned char pointer is pointing to a string allocated in
-  the dictionary, do not free or modify it.
- */
-/*--------------------------------------------------------------------------*/
-char * iniparser_getstring(dictionary * d, const char * key, char * def);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key, convert to an int
-  @param    d Dictionary to search
-  @param    key Key string to look for
-  @param    notfound Value to return in case of error
-  @return   integer
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the notfound value is returned.
-
-  Supported values for integers include the usual C notation
-  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
-  are supported. Examples:
-
-  - "42"      ->  42
-  - "042"     ->  34 (octal -> decimal)
-  - "0x42"    ->  66 (hexa  -> decimal)
-
-  Warning: the conversion may overflow in various ways. Conversion is
-  totally outsourced to strtol(), see the associated man page for overflow
-  handling.
-
-  Credits: Thanks to A. Becker for suggesting strtol()
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getint(dictionary * d, const char * key, int notfound);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key, convert to a double
-  @param    d Dictionary to search
-  @param    key Key string to look for
-  @param    notfound Value to return in case of error
-  @return   double
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the notfound value is returned.
- */
-/*--------------------------------------------------------------------------*/
-double iniparser_getdouble(dictionary * d, char * key, double notfound);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key, convert to a boolean
-  @param    d Dictionary to search
-  @param    key Key string to look for
-  @param    notfound Value to return in case of error
-  @return   integer
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the notfound value is returned.
-
-  A true boolean is found if one of the following is matched:
-
-  - A string starting with 'y'
-  - A string starting with 'Y'
-  - A string starting with 't'
-  - A string starting with 'T'
-  - A string starting with '1'
-
-  A false boolean is found if one of the following is matched:
-
-  - A string starting with 'n'
-  - A string starting with 'N'
-  - A string starting with 'f'
-  - A string starting with 'F'
-  - A string starting with '0'
-
-  The notfound value returned if no boolean is identified, does not
-  necessarily have to be 0 or 1.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getboolean(dictionary * d, const char * key, int notfound);
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Set an entry in a dictionary.
-  @param    ini     Dictionary to modify.
-  @param    entry   Entry to modify (entry name)
-  @param    val     New value to associate to the entry.
-  @return   int 0 if Ok, -1 otherwise.
-
-  If the given entry can be found in the dictionary, it is modified to
-  contain the provided value. If it cannot be found, -1 is returned.
-  It is Ok to set val to NULL.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_setstring(dictionary * ini, char * entry, char * val);
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Delete an entry in a dictionary
-  @param    ini     Dictionary to modify
-  @param    entry   Entry to delete (entry name)
-  @return   void
-
-  If the given entry can be found, it is deleted from the dictionary.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_unset(dictionary * ini, char * entry);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Finds out if a given entry exists in a dictionary
-  @param    ini     Dictionary to search
-  @param    entry   Name of the entry to look for
-  @return   integer 1 if entry exists, 0 otherwise
-
-  Finds out if a given entry exists in the dictionary. Since sections
-  are stored as keys with NULL associated values, this is the only way
-  of querying for the presence of sections in a dictionary.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_find_entry(dictionary * ini, char * entry) ;
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Parse an ini file and return an allocated dictionary object
-  @param    ininame Name of the ini file to read.
-  @return   Pointer to newly allocated dictionary
-
-  This is the parser for ini files. This function is called, providing
-  the name of the file to be read. It returns a dictionary object that
-  should not be accessed directly, but through accessor functions
-  instead.
-
-  The returned dictionary must be freed using iniparser_freedict().
- */
-/*--------------------------------------------------------------------------*/
-dictionary * iniparser_load(const char * ininame);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Free all memory associated to an ini dictionary
-  @param    d Dictionary to free
-  @return   void
-
-  Free all memory associated to an ini dictionary.
-  It is mandatory to call this function before the dictionary object
-  gets out of the current context.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_freedict(dictionary * d);
-
-#endif
diff --git a/ubi-utils/new-utils/include/libmtd.h b/ubi-utils/new-utils/include/libmtd.h
deleted file mode 100644
index d3c6a63..0000000
--- a/ubi-utils/new-utils/include/libmtd.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- *
- * Author: Artem Bityutskiy
- *
- * MTD library.
- */
-
-#ifndef __LIBMTD_H__
-#define __LIBMTD_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * struct mtd_info - information about an MTD device.
- * @num: MTD device number
- * @major: major number of corresponding character device
- * @minor: minor number of corresponding character device
- * @type: flash type (constants like %MTD_NANDFLASH defined in mtd-abi.h)
- * @type_str: static R/O flash type string
- * @size: device size in bytes
- * @eb_cnt: count of eraseblocks
- * @eb_size: eraseblock size
- * @min_io_size: minimum input/output unit size
- * @subpage_size: sub-page size (not set by 'mtd_get_info()'!!!)
- * @rdonly: non-zero if the device is read-only
- * @allows_bb: non-zero if the MTD device may have bad eraseblocks
- * @fd: descriptor of the opened MTD character device node
- */
-struct mtd_info
-{
-	int num;
-	int major;
-	int minor;
-	int type;
-	const char *type_str;
-	long long size;
-	int eb_cnt;
-	int eb_size;
-	int min_io_size;
-	int subpage_size;
-	unsigned int rdonly:1;
-	unsigned int allows_bb:1;
-	int fd;
-};
-
-int mtd_get_info(const char *node, struct mtd_info *mtd);
-int mtd_erase(const struct mtd_info *mtd, int eb);
-int mtd_is_bad(const struct mtd_info *mtd, int eb);
-int mtd_read(const struct mtd_info *mtd, int eb, int offs, void *buf, int len);
-int mtd_write(const struct mtd_info *mtd, int eb, int offs, void *buf, int len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __LIBMTD_H__ */
diff --git a/ubi-utils/new-utils/include/libscan.h b/ubi-utils/new-utils/include/libscan.h
deleted file mode 100644
index 5afc93e..0000000
--- a/ubi-utils/new-utils/include/libscan.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.
- *
- * Author: Artem Bityutskiy
- *
- * UBI scanning library.
- */
-
-#ifndef __LIBSCAN_H__
-#define __LIBSCAN_H__
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * If an eraseblock does not contain an erase counter, this value is used
- * instead of the erase counter.
- */
-#define NO_EC 0xFFFFFFFF
-
-/*
- * If an eraseblock contains a corrupted erase counter, this value is used
- * instead of the erase counter.
- */
-#define CORRUPT_EC 0xFFFFFFFE
-
-/*
- * If an eraseblock does not contain an erase counter, one of these values is
- * used.
- *
- * @EB_EMPTY: the eraseblock appeared to be empty
- * @EB_CORRUPTED: the eraseblock contains corrupted erase counter header
- * @EB_ALIEN: the eraseblock contains some non-UBI data
- * @EC_MAX: maximum allowed erase counter value
- */
-enum
-{
-	EB_EMPTY     = 0xFFFFFFFF,
-	EB_CORRUPTED = 0xFFFFFFFE,
-	EB_ALIEN     = 0xFFFFFFFD,
-	EB_BAD       = 0xFFFFFFFC,
-	EC_MAX       = UBI_MAX_ERASECOUNTER,
-};
-
-/**
- * struct ubi_scan_info - UBI scanning information.
- * @ec: erase counters or eraseblock status for all eraseblocks
- * @mean_ec: mean erase counter
- * @ok_cnt: count of eraseblock with correct erase counter header
- * @empty_cnt: count of supposedly eraseblocks
- * @corrupted_cnt: count of eraseblocks with corrupted erase counter header
- * @alien_cnt: count of eraseblock containing non-ubi data
- * @bad_cnt: count of bad eraseblocks
- * @bad_cnt: count of non-bad eraseblocks
- * @vid_hdr_offs: volume ID header offset from the found EC headers (%-1 means
- *                undefined)
- * @data_offs: data offset from the found EC headers (%-1 means undefined)
- */
-struct ubi_scan_info
-{
-	uint32_t *ec;
-	long long mean_ec;
-	int ok_cnt;
-	int empty_cnt;
-	int corrupted_cnt;
-	int alien_cnt;
-	int bad_cnt;
-	int good_cnt;
-	int vid_hdr_offs;
-	int data_offs;
-};
-
-struct mtd_info;
-
-/**
- * ubi_scan - scan an MTD device.
- * @mtd: information about the MTD device to scan
- * @info: the result of the scanning is returned here
- * @verbose: verbose mode: %0 - be silent, %1 - output progress information,
- *           2 - debugging output mode
- */
-int ubi_scan(struct mtd_info *mtd, struct ubi_scan_info **info, int verbose);
-
-/**
- * ubi_scan_free - free scanning information.
- * @si: scanning information to free
- */
-void ubi_scan_free(struct ubi_scan_info *si);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __LIBSCAN_H__ */
-
diff --git a/ubi-utils/new-utils/include/libubi.h b/ubi-utils/new-utils/include/libubi.h
deleted file mode 100644
index 1299e81..0000000
--- a/ubi-utils/new-utils/include/libubi.h
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Artem Bityutskiy
- *
- * UBI (Unsorted Block Images) library.
- */
-
-#ifndef __LIBUBI_H__
-#define __LIBUBI_H__
-
-#include <ctype.h>
-#include <stdint.h>
-#include <mtd/ubi-user.h>
-#include <mtd/ubi-media.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_id: lowest volume ID
- * @highest_vol_id: highest volume ID
- * @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_id;
-	int highest_vol_id;
-	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.
- * @required: if non-zero, libubi will print an error messages if this UBI is
- *            not present in the system
- *
- * 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(int required);
-
-/**
- * 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);
-
-/**
- * mtd_num2ubi_dev - find UBI device by attached MTD device.
- * @@desc: UBI library descriptor
- * @mtd_num: MTD device number
- * @dev_num: UBI device number is returned here
- *
- * This function finds UBI device to which MTD device @mtd_num is attached.
- * Returns %0 if the UBI device was found and %-1 if not.
- */
-int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num);
-
-/**
- * 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_rnvols - rename UBI volumes.
- * @desc: UBI library descriptor
- * @node: name of the UBI character device to remove a volume from
- * @rnvol: description of volumes to rename
- *
- * 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_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol);
-
-/**
- * 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 ID, 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_get_vol_info1_nm - get UBI volume information by volume name.
- * @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 name, not UBI volume ID.
- */
-int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name,
-			 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. The caller is assumed to write @bytes data to the
- * volume @fd afterwards.
- */
-int ubi_update_start(libubi_t desc, int fd, long long bytes);
-
-/**
- * ubi_leb_change_start - start atomic LEB change.
- * @desc: UBI library descriptor
- * @fd: volume character devie file descriptor
- * @lnum: LEB number to change
- * @bytes: how many bytes of new data will be written to the LEB
- * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
- *
- * This function initiates atomic LEB change operation and returns %0 in case
- * of success and %-1 in case of error. he caller is assumed to write @bytes
- * data to the volume @fd afterwards.
- */
-int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__LIBUBI_H__ */
diff --git a/ubi-utils/new-utils/include/libubigen.h b/ubi-utils/new-utils/include/libubigen.h
deleted file mode 100644
index c2b95b0..0000000
--- a/ubi-utils/new-utils/include/libubigen.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- * Copyright (C) 2008 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Authors: Frank Haverkamp
- *          Artem Bityutskiy
- */
-
-#ifndef __LIBUBIGEN_H__
-#define __LIBUBIGEN_H__
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * struct ubigen_info - libubigen information.
- * @leb_size: logical eraseblock size
- * @peb_size: size of the physical eraseblock
- * @min_io_size: minimum input/output unit size
- * @vid_hdr_offs: offset of the VID header
- * @data_offs: data offset
- * @ubi_ver: UBI version
- * @vtbl_size: volume table size
- * @max_volumes: maximum amount of volumes
- */
-struct ubigen_info
-{
-	int leb_size;
-	int peb_size;
-	int min_io_size;
-	int vid_hdr_offs;
-	int data_offs;
-	int ubi_ver;
-	int vtbl_size;
-	int max_volumes;
-};
-
-/**
- * struct ubigen_vol_info - information about a volume.
- * @id: volume id
- * @type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
- * @alignment: volume alignment
- * @data_pad: how many bytes are unused at the end of the each physical
- *            eraseblock to satisfy the requested alignment
- * @usable_leb_size: LEB size accessible for volume users
- * @name: volume name
- * @name_len: volume name length
- * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
- *          %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
- * @used_ebs: total number of used logical eraseblocks in this volume (relevant
- *            for static volumes only)
- * @bytes: size of the volume contents in bytes (relevant for static volumes
- *         only)
- * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
- */
-struct ubigen_vol_info
-{
-	int id;
-	int type;
-	int alignment;
-	int data_pad;
-	int usable_leb_size;
-	const char *name;
-	int name_len;
-	int compat;
-	int used_ebs;
-	long long bytes;
-	uint8_t flags;
-};
-
-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);
-struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui);
-void ubigen_init_ec_hdr(const struct ubigen_info *ui,
-		        struct ubi_ec_hdr *hdr, long long ec);
-int ubigen_get_vtbl_size(const struct ubigen_info *ui);
-int ubigen_add_volume(const struct ubigen_info *ui,
-		      const struct ubigen_vol_info *vi,
-		      struct ubi_vtbl_record *vtbl);
-int ubigen_write_volume(const struct ubigen_info *ui,
-			const struct ubigen_vol_info *vi, long long ec,
-			long long bytes, int in, int out);
-int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
-			    long long ec1, long long ec2,
-			    struct ubi_vtbl_record *vtbl, int fd);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__LIBUBIGEN_H__ */
diff --git a/ubi-utils/new-utils/src/common.c b/ubi-utils/new-utils/src/common.c
deleted file mode 100644
index bcb775c..0000000
--- a/ubi-utils/new-utils/src/common.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2007, 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.
- */
-
-/*
- * This file contains various common stuff used by UBI utilities.
- *
- * Authors: Artem Bityutskiy
- *          Adrian Hunter
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-/**
- * get_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.
- */
-static int 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;
-
-	/* Handle deprecated stuff */
-	if (!strcmp(str, "KB") || !strcmp(str, "Kib") || !strcmp(str, "kib") ||
-	    !strcmp(str, "kiB")) {
-		fprintf(stderr, "Warning: use \"KiB\" instead of \"%s\" to "
-			"specify Kilobytes - support will be removed\n", str);
-		return 1024;
-	}
-	if (!strcmp(str, "MB") || !strcmp(str, "Mib") || !strcmp(str, "mb")) {
-		fprintf(stderr, "Warning: use \"MiB\" instead of \"%s\", "
-			"this support will be removed\n", str);
-		return 1024*1024;
-	}
-	if (!strcmp(str, "GB") || !strcmp(str, "Gib") || !strcmp(str, "gb")) {
-		fprintf(stderr, "Warning: use \"GiB\" instead of \"%s\", "
-			"this support will be removed\n", str);
-		return 1024*1024*1024;
-	}
-
-	return -1;
-}
-
-/**
- * ubiutils_get_bytes - convert a string containing amount of bytes into an
- * integer
- * @str: string to convert
- *
- * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
- * size specifiers. Returns positive amount of bytes in case of success and %-1
- * in case of failure.
- */
-long long ubiutils_get_bytes(const char *str)
-{
-	char *endp;
-	long long bytes = strtoull(str, &endp, 0);
-
-	if (endp == str || bytes < 0) {
-		fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str);
-		return -1;
-	}
-
-	if (*endp != '\0') {
-		int mult = get_multiplier(endp);
-
-		if (mult == -1) {
-			fprintf(stderr, "bad size specifier: \"%s\" - "
-			        "should be 'KiB', 'MiB' or 'GiB'\n", endp);
-			return -1;
-		}
-		bytes *= mult;
-	}
-
-	return bytes;
-}
-
-/**
- * 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 && bytes != 0)
-		printf("%s%.1f KiB", p, (double)bytes / 1024);
-	else
-		return;
-
-	if (bracket)
-		printf(")");
-}
-
-/**
- * ubiutils_print_text - print text and fold it.
- * @stream: file stream to print to
- * @text: text to print
- * @width: maximum allowed text width
- *
- * Print text and fold it so that each line would not have more then @width
- * characters.
- */
-void ubiutils_print_text(FILE *stream, const char *text, int width)
-{
-	int pos, bpos = 0;
-	const char *p;
-	char line[1024];
-
-	if (width > 1023) {
-		fprintf(stream, "%s\n", text);
-		return;
-	}
-	p = text;
-	pos = 0;
-	while (p[pos]) {
-		while (!isspace(p[pos])) {
-			line[pos] = p[pos];
-			if (!p[pos])
-				break;
-			++pos;
-			if (pos == width) {
-				line[pos] = '\0';
-				fprintf(stream, "%s\n", line);
-				p += pos;
-				pos = 0;
-			}
-		}
-		while (pos < width) {
-			line[pos] = p[pos];
-			if (!p[pos]) {
-				bpos = pos;
-				break;
-			}
-			if (isspace(p[pos]))
-				bpos = pos;
-			++pos;
-		}
-		line[bpos] = '\0';
-		fprintf(stream, "%s\n", line);
-		p += bpos;
-		pos = 0;
-		while (p[pos] && isspace(p[pos]))
-			++p;
-	}
-}
diff --git a/ubi-utils/new-utils/src/common.h b/ubi-utils/new-utils/src/common.h
deleted file mode 100644
index 56fa020..0000000
--- a/ubi-utils/new-utils/src/common.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) Artem Bityutskiy, 2007, 2008
- *
- * 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__
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MIN(a ,b) ((a) < (b) ? (a) : (b))
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-/* Verbose messages */
-#define verbose(verbose, fmt, ...) do {                            \
-	if (verbose)                                               \
-		printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \
-} while(0)
-
-/* Normal messages */
-#define normsg(fmt, ...) do {                              \
-	printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \
-} while(0)
-#define normsg_cont(fmt, ...) do {                    \
-	printf(PROGRAM_NAME ": " fmt, ##__VA_ARGS__); \
-} while(0)
-#define normsg_cont(fmt, ...) do {                         \
-	printf(PROGRAM_NAME ": " fmt, ##__VA_ARGS__);      \
-} while(0)
-
-/* Error messages */
-#define errmsg(fmt, ...)  ({                                                \
-	fprintf(stderr, PROGRAM_NAME ": error!: " fmt "\n", ##__VA_ARGS__); \
-	-1;                                                                 \
-})
-
-/* System error messages */
-#define sys_errmsg(fmt, ...)  ({                                            \
-	int _err = errno;                                                   \
-	size_t _i;                                                           \
-	fprintf(stderr, PROGRAM_NAME ": error!: " fmt "\n", ##__VA_ARGS__); \
-	for (_i = 0; _i < sizeof(PROGRAM_NAME) + 1; _i++)                   \
-		fprintf(stderr, " ");                                       \
-	fprintf(stderr, "error %d (%s)\n", _err, strerror(_err));           \
-	-1;                                                                 \
-})
-
-/* Warnings */
-#define warnmsg(fmt, ...) do {                                                \
-	fprintf(stderr, PROGRAM_NAME ": warning!: " fmt "\n", ##__VA_ARGS__); \
-} while(0)
-
-static inline int is_power_of_2(unsigned long long n)
-{
-	        return (n != 0 && ((n & (n - 1)) == 0));
-}
-
-long long ubiutils_get_bytes(const char *str);
-void ubiutils_print_bytes(long long bytes, int bracket);
-void ubiutils_print_text(FILE *stream, const char *txt, int len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__UBI_UTILS_COMMON_H__ */
diff --git a/ubi-utils/new-utils/src/crc32.c b/ubi-utils/new-utils/src/crc32.c
deleted file mode 100644
index 6b1e50c..0000000
--- a/ubi-utils/new-utils/src/crc32.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
- *  code or tables extracted from it, as desired without restriction.
- *
- *  First, the polynomial itself and its table of feedback terms.  The
- *  polynomial is
- *  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
- *
- *  Note that we take it "backwards" and put the highest-order term in
- *  the lowest-order bit.  The X^32 term is "implied"; the LSB is the
- *  X^31 term, etc.  The X^0 term (usually shown as "+1") results in
- *  the MSB being 1
- *
- *  Note that the usual hardware shift register implementation, which
- *  is what we're using (we're merely optimizing it by doing eight-bit
- *  chunks at a time) shifts bits into the lowest-order term.  In our
- *  implementation, that means shifting towards the right.  Why do we
- *  do it this way?  Because the calculated CRC must be transmitted in
- *  order from highest-order term to lowest-order term.  UARTs transmit
- *  characters in order from LSB to MSB.  By storing the CRC this way
- *  we hand it to the UART in the order low-byte to high-byte; the UART
- *  sends each low-bit to hight-bit; and the result is transmission bit
- *  by bit from highest- to lowest-order term without requiring any bit
- *  shuffling on our part.  Reception works similarly
- *
- *  The feedback terms table consists of 256, 32-bit entries.  Notes
- *
- *      The table can be generated at runtime if desired; code to do so
- *      is shown later.  It might not be obvious, but the feedback
- *      terms simply represent the results of eight shift/xor opera
- *      tions for all combinations of data and CRC register values
- *
- *      The values must be right-shifted by eight bits by the "updcrc
- *      logic; the shift must be unsigned (bring in zeroes).  On some
- *      hardware you could probably optimize the shift in assembler by
- *      using byte-swap instructions
- *      polynomial $edb88320
- */
-
-#include <stdint.h>
-
-const uint32_t crc32_table[256] = {
-	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
-	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
-	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
-	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
-	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
-	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
-	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
-	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
-	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
-	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
-	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
-	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
-	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
-	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
-	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
-	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
-	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
-	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
-	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
-	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
-	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
-	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
-	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
-	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
-	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
-	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
-	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
-	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
-	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
-	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
-	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
-	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
-	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
-	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
-	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
-	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
-	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
-	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
-	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
-	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
-	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
-	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
-	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
-	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
-	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
-	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
-	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
-	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
-	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
-	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
-	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
-	0x2d02ef8dL
-};
diff --git a/ubi-utils/new-utils/src/crc32.h b/ubi-utils/new-utils/src/crc32.h
deleted file mode 100644
index ee3145b..0000000
--- a/ubi-utils/new-utils/src/crc32.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef CRC32_H
-#define CRC32_H
-
-#include <stdint.h>
-
-extern const uint32_t crc32_table[256];
-
-/* Return a 32-bit CRC of the contents of the buffer. */
-
-	static inline uint32_t
-crc32(uint32_t val, const void *ss, int len)
-{
-	const unsigned char *s = ss;
-	while (--len >= 0)
-		val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
-	return val;
-}
-
-#endif
diff --git a/ubi-utils/new-utils/src/dictionary.c b/ubi-utils/new-utils/src/dictionary.c
deleted file mode 100644
index b7c9ebf..0000000
--- a/ubi-utils/new-utils/src/dictionary.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*-------------------------------------------------------------------------*/
-/**
-   @file	dictionary.c
-   @author	N. Devillard
-   @date	Sep 2007
-   @version	$Revision: 1.27 $
-   @brief	Implements a dictionary for string variables.
-
-   This module implements a simple dictionary object, i.e. a list
-   of string/string associations. This object is useful to store e.g.
-   informations retrieved from a configuration file (ini files).
-*/
-/*--------------------------------------------------------------------------*/
-
-/*
-	$Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $
-	$Revision: 1.27 $
-*/
-/*---------------------------------------------------------------------------
-   								Includes
- ---------------------------------------------------------------------------*/
-#include "dictionary.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/** Maximum value size for integers and doubles. */
-#define MAXVALSZ	1024
-
-/** Minimal allocated number of entries in a dictionary */
-#define DICTMINSZ	128
-
-/** Invalid key token */
-#define DICT_INVALID_KEY    ((char*)-1)
-
-/*---------------------------------------------------------------------------
-  							Private functions
- ---------------------------------------------------------------------------*/
-
-/* Doubles the allocated size associated to a pointer */
-/* 'size' is the current allocated size. */
-static void * mem_double(void * ptr, int size)
-{
-    void * newptr ;
- 
-    newptr = calloc(2*size, 1);
-    if (newptr==NULL) {
-        return NULL ;
-    }
-    memcpy(newptr, ptr, size);
-    free(ptr);
-    return newptr ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Duplicate a string
-  @param    s String to duplicate
-  @return   Pointer to a newly allocated string, to be freed with free()
-
-  This is a replacement for strdup(). This implementation is provided
-  for systems that do not have it.
- */
-/*--------------------------------------------------------------------------*/
-static char * xstrdup(char * s)
-{
-    char * t ;
-    if (!s)
-        return NULL ;
-    t = malloc(strlen(s)+1) ;
-    if (t) {
-        strcpy(t,s);
-    }
-    return t ;
-}
-
-/*---------------------------------------------------------------------------
-  							Function codes
- ---------------------------------------------------------------------------*/
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Compute the hash key for a string.
-  @param	key		Character string to use for key.
-  @return	1 unsigned int on at least 32 bits.
-
-  This hash function has been taken from an Article in Dr Dobbs Journal.
-  This is normally a collision-free function, distributing keys evenly.
-  The key is stored anyway in the struct so that collision can be avoided
-  by comparing the key itself in last resort.
- */
-/*--------------------------------------------------------------------------*/
-unsigned dictionary_hash(char * key)
-{
-	int			len ;
-	unsigned	hash ;
-	int			i ;
-
-	len = strlen(key);
-	for (hash=0, i=0 ; i<len ; i++) {
-		hash += (unsigned)key[i] ;
-		hash += (hash<<10);
-		hash ^= (hash>>6) ;
-	}
-	hash += (hash <<3);
-	hash ^= (hash >>11);
-	hash += (hash <<15);
-	return hash ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Create a new dictionary object.
-  @param	size	Optional initial size of the dictionary.
-  @return	1 newly allocated dictionary objet.
-
-  This function allocates a new dictionary object of given size and returns
-  it. If you do not know in advance (roughly) the number of entries in the
-  dictionary, give size=0.
- */
-/*--------------------------------------------------------------------------*/
-dictionary * dictionary_new(int size)
-{
-	dictionary	*	d ;
-
-	/* If no size was specified, allocate space for DICTMINSZ */
-	if (size<DICTMINSZ) size=DICTMINSZ ;
-
-	if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
-		return NULL;
-	}
-	d->size = size ;
-	d->val  = (char **)calloc(size, sizeof(char*));
-	d->key  = (char **)calloc(size, sizeof(char*));
-	d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
-	return d ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Delete a dictionary object
-  @param	d	dictionary object to deallocate.
-  @return	void
-
-  Deallocate a dictionary object and all memory associated to it.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_del(dictionary * d)
-{
-	int		i ;
-
-	if (d==NULL) return ;
-	for (i=0 ; i<d->size ; i++) {
-		if (d->key[i]!=NULL)
-			free(d->key[i]);
-		if (d->val[i]!=NULL)
-			free(d->val[i]);
-	}
-	free(d->val);
-	free(d->key);
-	free(d->hash);
-	free(d);
-	return ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Get a value from a dictionary.
-  @param	d		dictionary object to search.
-  @param	key		Key to look for in the dictionary.
-  @param    def     Default value to return if key not found.
-  @return	1 pointer to internally allocated character string.
-
-  This function locates a key in a dictionary and returns a pointer to its
-  value, or the passed 'def' pointer if no such key can be found in
-  dictionary. The returned character pointer points to data internal to the
-  dictionary object, you should not try to free it or modify it.
- */
-/*--------------------------------------------------------------------------*/
-char * dictionary_get(dictionary * d, char * key, char * def)
-{
-	unsigned	hash ;
-	int			i ;
-
-	hash = dictionary_hash(key);
-	for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        /* Compare hash */
-		if (hash==d->hash[i]) {
-            /* Compare string, to avoid hash collisions */
-            if (!strcmp(key, d->key[i])) {
-				return d->val[i] ;
-			}
-		}
-	}
-	return def ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Set a value in a dictionary.
-  @param    d       dictionary object to modify.
-  @param    key     Key to modify or add.
-  @param    val     Value to add.
-  @return   int     0 if Ok, anything else otherwise
-
-  If the given key is found in the dictionary, the associated value is
-  replaced by the provided one. If the key cannot be found in the
-  dictionary, it is added to it.
-
-  It is Ok to provide a NULL value for val, but NULL values for the dictionary
-  or the key are considered as errors: the function will return immediately
-  in such a case.
-
-  Notice that if you dictionary_set a variable to NULL, a call to
-  dictionary_get will return a NULL value: the variable will be found, and
-  its value (NULL) is returned. In other words, setting the variable
-  content to NULL is equivalent to deleting the variable from the
-  dictionary. It is not possible (in this implementation) to have a key in
-  the dictionary without value.
-
-  This function returns non-zero in case of failure.
- */
-/*--------------------------------------------------------------------------*/
-int dictionary_set(dictionary * d, char * key, char * val)
-{
-	int			i ;
-	unsigned	hash ;
-
-	if (d==NULL || key==NULL) return -1 ;
-	
-	/* Compute hash for this key */
-	hash = dictionary_hash(key) ;
-	/* Find if value is already in dictionary */
-	if (d->n>0) {
-		for (i=0 ; i<d->size ; i++) {
-            if (d->key[i]==NULL)
-                continue ;
-			if (hash==d->hash[i]) { /* Same hash value */
-				if (!strcmp(key, d->key[i])) {	 /* Same key */
-					/* Found a value: modify and return */
-					if (d->val[i]!=NULL)
-						free(d->val[i]);
-                    d->val[i] = val ? xstrdup(val) : NULL ;
-                    /* Value has been modified: return */
-					return 0 ;
-				}
-			}
-		}
-	}
-	/* Add a new value */
-	/* See if dictionary needs to grow */
-	if (d->n==d->size) {
-
-		/* Reached maximum size: reallocate dictionary */
-		d->val  = (char **)mem_double(d->val,  d->size * sizeof(char*)) ;
-		d->key  = (char **)mem_double(d->key,  d->size * sizeof(char*)) ;
-		d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
-        if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
-            /* Cannot grow dictionary */
-            return -1 ;
-        }
-		/* Double size */
-		d->size *= 2 ;
-	}
-
-    /* Insert key in the first empty slot */
-    for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL) {
-            /* Add key here */
-            break ;
-        }
-    }
-	/* Copy key */
-	d->key[i]  = xstrdup(key);
-    d->val[i]  = val ? xstrdup(val) : NULL ;
-	d->hash[i] = hash;
-	d->n ++ ;
-	return 0 ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Delete a key in a dictionary
-  @param	d		dictionary object to modify.
-  @param	key		Key to remove.
-  @return   void
-
-  This function deletes a key in a dictionary. Nothing is done if the
-  key cannot be found.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_unset(dictionary * d, char * key)
-{
-	unsigned	hash ;
-	int			i ;
-
-	if (key == NULL) {
-		return;
-	}
-
-	hash = dictionary_hash(key);
-	for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        /* Compare hash */
-		if (hash==d->hash[i]) {
-            /* Compare string, to avoid hash collisions */
-            if (!strcmp(key, d->key[i])) {
-                /* Found key */
-                break ;
-			}
-		}
-	}
-    if (i>=d->size)
-        /* Key not found */
-        return ;
-
-    free(d->key[i]);
-    d->key[i] = NULL ;
-    if (d->val[i]!=NULL) {
-        free(d->val[i]);
-        d->val[i] = NULL ;
-    }
-    d->hash[i] = 0 ;
-    d->n -- ;
-    return ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Dump a dictionary to an opened file pointer.
-  @param	d	Dictionary to dump
-  @param	f	Opened file pointer.
-  @return	void
-
-  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
-  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
-  output file pointers.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_dump(dictionary * d, FILE * out)
-{
-	int		i ;
-
-	if (d==NULL || out==NULL) return ;
-	if (d->n<1) {
-		fprintf(out, "empty dictionary\n");
-		return ;
-	}
-	for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]) {
-            fprintf(out, "%20s\t[%s]\n",
-                    d->key[i],
-                    d->val[i] ? d->val[i] : "UNDEF");
-        }
-	}
-	return ;
-}
-
-
-/* Test code */
-#ifdef TESTDIC
-#define NVALS 20000
-int main(int argc, char *argv[])
-{
-	dictionary	*	d ;
-	char	*	val ;
-	int			i ;
-	char		cval[90] ;
-
-	/* Allocate dictionary */
-	printf("allocating...\n");
-	d = dictionary_new(0);
-	
-	/* Set values in dictionary */
-	printf("setting %d values...\n", NVALS);
-	for (i=0 ; i<NVALS ; i++) {
-		sprintf(cval, "%04d", i);
-		dictionary_set(d, cval, "salut");
-	}
-	printf("getting %d values...\n", NVALS);
-	for (i=0 ; i<NVALS ; i++) {
-		sprintf(cval, "%04d", i);
-		val = dictionary_get(d, cval, DICT_INVALID_KEY);
-		if (val==DICT_INVALID_KEY) {
-			printf("cannot get value for key [%s]\n", cval);
-		}
-	}
-    printf("unsetting %d values...\n", NVALS);
-	for (i=0 ; i<NVALS ; i++) {
-		sprintf(cval, "%04d", i);
-		dictionary_unset(d, cval);
-	}
-    if (d->n != 0) {
-        printf("error deleting values\n");
-    }
-	printf("deallocating...\n");
-	dictionary_del(d);
-	return 0 ;
-}
-#endif
-/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/ubi-utils/new-utils/src/dictionary.h b/ubi-utils/new-utils/src/dictionary.h
deleted file mode 100644
index c7d1790..0000000
--- a/ubi-utils/new-utils/src/dictionary.h
+++ /dev/null
@@ -1,174 +0,0 @@
-
-/*-------------------------------------------------------------------------*/
-/**
-   @file    dictionary.h
-   @author  N. Devillard
-   @date    Sep 2007
-   @version $Revision: 1.12 $
-   @brief   Implements a dictionary for string variables.
-
-   This module implements a simple dictionary object, i.e. a list
-   of string/string associations. This object is useful to store e.g.
-   informations retrieved from a configuration file (ini files).
-*/
-/*--------------------------------------------------------------------------*/
-
-/*
-	$Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $
-	$Author: ndevilla $
-	$Date: 2007-11-23 21:37:00 $
-	$Revision: 1.12 $
-*/
-
-#ifndef _DICTIONARY_H_
-#define _DICTIONARY_H_
-
-/*---------------------------------------------------------------------------
-   								Includes
- ---------------------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/*---------------------------------------------------------------------------
-   								New types
- ---------------------------------------------------------------------------*/
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Dictionary object
-
-  This object contains a list of string/string associations. Each
-  association is identified by a unique string key. Looking up values
-  in the dictionary is speeded up by the use of a (hopefully collision-free)
-  hash function.
- */
-/*-------------------------------------------------------------------------*/
-typedef struct _dictionary_ {
-	int				n ;		/** Number of entries in dictionary */
-	int				size ;	/** Storage size */
-	char 		**	val ;	/** List of string values */
-	char 		**  key ;	/** List of string keys */
-	unsigned	 *	hash ;	/** List of hash values for keys */
-} dictionary ;
-
-
-/*---------------------------------------------------------------------------
-  							Function prototypes
- ---------------------------------------------------------------------------*/
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Compute the hash key for a string.
-  @param    key     Character string to use for key.
-  @return   1 unsigned int on at least 32 bits.
-
-  This hash function has been taken from an Article in Dr Dobbs Journal.
-  This is normally a collision-free function, distributing keys evenly.
-  The key is stored anyway in the struct so that collision can be avoided
-  by comparing the key itself in last resort.
- */
-/*--------------------------------------------------------------------------*/
-unsigned dictionary_hash(char * key);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Create a new dictionary object.
-  @param    size    Optional initial size of the dictionary.
-  @return   1 newly allocated dictionary objet.
-
-  This function allocates a new dictionary object of given size and returns
-  it. If you do not know in advance (roughly) the number of entries in the
-  dictionary, give size=0.
- */
-/*--------------------------------------------------------------------------*/
-dictionary * dictionary_new(int size);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Delete a dictionary object
-  @param    d   dictionary object to deallocate.
-  @return   void
-
-  Deallocate a dictionary object and all memory associated to it.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_del(dictionary * vd);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get a value from a dictionary.
-  @param    d       dictionary object to search.
-  @param    key     Key to look for in the dictionary.
-  @param    def     Default value to return if key not found.
-  @return   1 pointer to internally allocated character string.
-
-  This function locates a key in a dictionary and returns a pointer to its
-  value, or the passed 'def' pointer if no such key can be found in
-  dictionary. The returned character pointer points to data internal to the
-  dictionary object, you should not try to free it or modify it.
- */
-/*--------------------------------------------------------------------------*/
-char * dictionary_get(dictionary * d, char * key, char * def);
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Set a value in a dictionary.
-  @param    d       dictionary object to modify.
-  @param    key     Key to modify or add.
-  @param    val     Value to add.
-  @return   int     0 if Ok, anything else otherwise
-
-  If the given key is found in the dictionary, the associated value is
-  replaced by the provided one. If the key cannot be found in the
-  dictionary, it is added to it.
-
-  It is Ok to provide a NULL value for val, but NULL values for the dictionary
-  or the key are considered as errors: the function will return immediately
-  in such a case.
-
-  Notice that if you dictionary_set a variable to NULL, a call to
-  dictionary_get will return a NULL value: the variable will be found, and
-  its value (NULL) is returned. In other words, setting the variable
-  content to NULL is equivalent to deleting the variable from the
-  dictionary. It is not possible (in this implementation) to have a key in
-  the dictionary without value.
-
-  This function returns non-zero in case of failure.
- */
-/*--------------------------------------------------------------------------*/
-int dictionary_set(dictionary * vd, char * key, char * val);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Delete a key in a dictionary
-  @param    d       dictionary object to modify.
-  @param    key     Key to remove.
-  @return   void
-
-  This function deletes a key in a dictionary. Nothing is done if the
-  key cannot be found.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_unset(dictionary * d, char * key);
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Dump a dictionary to an opened file pointer.
-  @param    d   Dictionary to dump
-  @param    f   Opened file pointer.
-  @return   void
-
-  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
-  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
-  output file pointers.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_dump(dictionary * d, FILE * out);
-
-#endif
diff --git a/ubi-utils/new-utils/src/libiniparser.c b/ubi-utils/new-utils/src/libiniparser.c
deleted file mode 100644
index 3bea51e..0000000
--- a/ubi-utils/new-utils/src/libiniparser.c
+++ /dev/null
@@ -1,646 +0,0 @@
-
-/*-------------------------------------------------------------------------*/
-/**
-   @file    iniparser.c
-   @author  N. Devillard
-   @date    Sep 2007
-   @version 3.0
-   @brief   Parser for ini files.
-*/
-/*--------------------------------------------------------------------------*/
-/*
-    $Id: iniparser.c,v 2.18 2008-01-03 18:35:39 ndevilla Exp $
-    $Revision: 2.18 $
-    $Date: 2008-01-03 18:35:39 $
-*/
-/*---------------------------- Includes ------------------------------------*/
-#include <ctype.h>
-#include <libiniparser.h>
-
-/*---------------------------- Defines -------------------------------------*/
-#define ASCIILINESZ         (1024)
-#define INI_INVALID_KEY     ((char*)-1)
-
-/*---------------------------------------------------------------------------
-                        Private to this module
- ---------------------------------------------------------------------------*/
-/**
- * This enum stores the status for each parsed line (internal use only).
- */
-typedef enum _line_status_ {
-    LINE_UNPROCESSED,
-    LINE_ERROR,
-    LINE_EMPTY,
-    LINE_COMMENT,
-    LINE_SECTION,
-    LINE_VALUE
-} line_status ;
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Convert a string to lowercase.
-  @param	s	String to convert.
-  @return	ptr to statically allocated string.
-
-  This function returns a pointer to a statically allocated string
-  containing a lowercased version of the input string. Do not free
-  or modify the returned string! Since the returned string is statically
-  allocated, it will be modified at each function call (not re-entrant).
- */
-/*--------------------------------------------------------------------------*/
-static char * strlwc(const char * s)
-{
-    static char l[ASCIILINESZ+1];
-    int i ;
-
-    if (s==NULL) return NULL ;
-    memset(l, 0, ASCIILINESZ+1);
-    i=0 ;
-    while (s[i] && i<ASCIILINESZ) {
-        l[i] = (char)tolower((int)s[i]);
-        i++ ;
-    }
-    l[ASCIILINESZ]=(char)0;
-    return l ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Remove blanks at the beginning and the end of a string.
-  @param	s	String to parse.
-  @return	ptr to statically allocated string.
-
-  This function returns a pointer to a statically allocated string,
-  which is identical to the input string, except that all blank
-  characters at the end and the beg. of the string have been removed.
-  Do not free or modify the returned string! Since the returned string
-  is statically allocated, it will be modified at each function call
-  (not re-entrant).
- */
-/*--------------------------------------------------------------------------*/
-static char * strstrip(char * s)
-{
-    static char l[ASCIILINESZ+1];
-	char * last ;
-	
-    if (s==NULL) return NULL ;
-    
-	while (isspace((int)*s) && *s) s++;
-	memset(l, 0, ASCIILINESZ+1);
-	strcpy(l, s);
-	last = l + strlen(l);
-	while (last > l) {
-		if (!isspace((int)*(last-1)))
-			break ;
-		last -- ;
-	}
-	*last = (char)0;
-	return (char*)l ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get number of sections in a dictionary
-  @param    d   Dictionary to examine
-  @return   int Number of sections found in dictionary
-
-  This function returns the number of sections found in a dictionary.
-  The test to recognize sections is done on the string stored in the
-  dictionary: a section name is given as "section" whereas a key is
-  stored as "section:key", thus the test looks for entries that do not
-  contain a colon.
-
-  This clearly fails in the case a section name contains a colon, but
-  this should simply be avoided.
-
-  This function returns -1 in case of error.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getnsec(dictionary * d)
-{
-    int i ;
-    int nsec ;
-
-    if (d==NULL) return -1 ;
-    nsec=0 ;
-    for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        if (strchr(d->key[i], ':')==NULL) {
-            nsec ++ ;
-        }
-    }
-    return nsec ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get name for section n in a dictionary.
-  @param    d   Dictionary to examine
-  @param    n   Section number (from 0 to nsec-1).
-  @return   Pointer to char string
-
-  This function locates the n-th section in a dictionary and returns
-  its name as a pointer to a string statically allocated inside the
-  dictionary. Do not free or modify the returned string!
-
-  This function returns NULL in case of error.
- */
-/*--------------------------------------------------------------------------*/
-char * iniparser_getsecname(dictionary * d, int n)
-{
-    int i ;
-    int foundsec ;
-
-    if (d==NULL || n<0) return NULL ;
-    foundsec=0 ;
-    for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        if (strchr(d->key[i], ':')==NULL) {
-            foundsec++ ;
-            if (foundsec>n)
-                break ;
-        }
-    }
-    if (foundsec<=n) {
-        return NULL ;
-    }
-    return d->key[i] ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Dump a dictionary to an opened file pointer.
-  @param    d   Dictionary to dump.
-  @param    f   Opened file pointer to dump to.
-  @return   void
-
-  This function prints out the contents of a dictionary, one element by
-  line, onto the provided file pointer. It is OK to specify @c stderr
-  or @c stdout as output files. This function is meant for debugging
-  purposes mostly.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_dump(dictionary * d, FILE * f)
-{
-    int     i ;
-
-    if (d==NULL || f==NULL) return ;
-    for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        if (d->val[i]!=NULL) {
-            fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
-        } else {
-            fprintf(f, "[%s]=UNDEF\n", d->key[i]);
-        }
-    }
-    return ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Save a dictionary to a loadable ini file
-  @param    d   Dictionary to dump
-  @param    f   Opened file pointer to dump to
-  @return   void
-
-  This function dumps a given dictionary into a loadable ini file.
-  It is Ok to specify @c stderr or @c stdout as output files.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_dump_ini(dictionary * d, FILE * f)
-{
-    int     i, j ;
-    char    keym[ASCIILINESZ+1];
-    int     nsec ;
-    char *  secname ;
-    int     seclen ;
-
-    if (d==NULL || f==NULL) return ;
-
-    nsec = iniparser_getnsec(d);
-    if (nsec<1) {
-        /* No section in file: dump all keys as they are */
-        for (i=0 ; i<d->size ; i++) {
-            if (d->key[i]==NULL)
-                continue ;
-            fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
-        }
-        return ;
-    }
-    for (i=0 ; i<nsec ; i++) {
-        secname = iniparser_getsecname(d, i) ;
-        seclen  = (int)strlen(secname);
-        fprintf(f, "\n[%s]\n", secname);
-        sprintf(keym, "%s:", secname);
-        for (j=0 ; j<d->size ; j++) {
-            if (d->key[j]==NULL)
-                continue ;
-            if (!strncmp(d->key[j], keym, seclen+1)) {
-                fprintf(f,
-                        "%-30s = %s\n",
-                        d->key[j]+seclen+1,
-                        d->val[j] ? d->val[j] : "");
-            }
-        }
-    }
-    fprintf(f, "\n");
-    return ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key
-  @param    d       Dictionary to search
-  @param    key     Key string to look for
-  @param    def     Default value to return if key not found.
-  @return   pointer to statically allocated character string
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the pointer passed as 'def' is returned.
-  The returned char pointer is pointing to a string allocated in
-  the dictionary, do not free or modify it.
- */
-/*--------------------------------------------------------------------------*/
-char * iniparser_getstring(dictionary * d, const char * key, char * def)
-{
-    char * lc_key ;
-    char * sval ;
-
-    if (d==NULL || key==NULL)
-        return def ;
-
-    lc_key = strlwc(key);
-    sval = dictionary_get(d, lc_key, def);
-    return sval ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key, convert to an int
-  @param    d Dictionary to search
-  @param    key Key string to look for
-  @param    notfound Value to return in case of error
-  @return   integer
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the notfound value is returned.
-
-  Supported values for integers include the usual C notation
-  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
-  are supported. Examples:
-
-  "42"      ->  42
-  "042"     ->  34 (octal -> decimal)
-  "0x42"    ->  66 (hexa  -> decimal)
-
-  Warning: the conversion may overflow in various ways. Conversion is
-  totally outsourced to strtol(), see the associated man page for overflow
-  handling.
-
-  Credits: Thanks to A. Becker for suggesting strtol()
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getint(dictionary * d, const char * key, int notfound)
-{
-    char    *   str ;
-
-    str = iniparser_getstring(d, key, INI_INVALID_KEY);
-    if (str==INI_INVALID_KEY) return notfound ;
-    return (int)strtol(str, NULL, 0);
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key, convert to a double
-  @param    d Dictionary to search
-  @param    key Key string to look for
-  @param    notfound Value to return in case of error
-  @return   double
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the notfound value is returned.
- */
-/*--------------------------------------------------------------------------*/
-double iniparser_getdouble(dictionary * d, char * key, double notfound)
-{
-    char    *   str ;
-
-    str = iniparser_getstring(d, key, INI_INVALID_KEY);
-    if (str==INI_INVALID_KEY) return notfound ;
-    return atof(str);
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key, convert to a boolean
-  @param    d Dictionary to search
-  @param    key Key string to look for
-  @param    notfound Value to return in case of error
-  @return   integer
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the notfound value is returned.
-
-  A true boolean is found if one of the following is matched:
-
-  - A string starting with 'y'
-  - A string starting with 'Y'
-  - A string starting with 't'
-  - A string starting with 'T'
-  - A string starting with '1'
-
-  A false boolean is found if one of the following is matched:
-
-  - A string starting with 'n'
-  - A string starting with 'N'
-  - A string starting with 'f'
-  - A string starting with 'F'
-  - A string starting with '0'
-
-  The notfound value returned if no boolean is identified, does not
-  necessarily have to be 0 or 1.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getboolean(dictionary * d, const char * key, int notfound)
-{
-    char    *   c ;
-    int         ret ;
-
-    c = iniparser_getstring(d, key, INI_INVALID_KEY);
-    if (c==INI_INVALID_KEY) return notfound ;
-    if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
-        ret = 1 ;
-    } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
-        ret = 0 ;
-    } else {
-        ret = notfound ;
-    }
-    return ret;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Finds out if a given entry exists in a dictionary
-  @param    ini     Dictionary to search
-  @param    entry   Name of the entry to look for
-  @return   integer 1 if entry exists, 0 otherwise
-
-  Finds out if a given entry exists in the dictionary. Since sections
-  are stored as keys with NULL associated values, this is the only way
-  of querying for the presence of sections in a dictionary.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_find_entry(
-    dictionary  *   ini,
-    char        *   entry
-)
-{
-    int found=0 ;
-    if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
-        found = 1 ;
-    }
-    return found ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Set an entry in a dictionary.
-  @param    ini     Dictionary to modify.
-  @param    entry   Entry to modify (entry name)
-  @param    val     New value to associate to the entry.
-  @return   int 0 if Ok, -1 otherwise.
-
-  If the given entry can be found in the dictionary, it is modified to
-  contain the provided value. If it cannot be found, -1 is returned.
-  It is Ok to set val to NULL.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_set(dictionary * ini, char * entry, char * val)
-{
-    return dictionary_set(ini, strlwc(entry), val) ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Delete an entry in a dictionary
-  @param    ini     Dictionary to modify
-  @param    entry   Entry to delete (entry name)
-  @return   void
-
-  If the given entry can be found, it is deleted from the dictionary.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_unset(dictionary * ini, char * entry)
-{
-    dictionary_unset(ini, strlwc(entry));
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Load a single line from an INI file
-  @param    input_line  Input line, may be concatenated multi-line input
-  @param    section     Output space to store section
-  @param    key         Output space to store key
-  @param    value       Output space to store value
-  @return   line_status value
- */
-/*--------------------------------------------------------------------------*/
-static line_status iniparser_line(
-    char * input_line,
-    char * section,
-    char * key,
-    char * value)
-{   
-    line_status sta ;
-    char        line[ASCIILINESZ+1];
-    int         len ;
-
-    strcpy(line, strstrip(input_line));
-    len = (int)strlen(line);
-
-    sta = LINE_UNPROCESSED ;
-    if (len<1) {
-        /* Empty line */
-        sta = LINE_EMPTY ;
-    } else if (line[0]=='#') {
-        /* Comment line */
-        sta = LINE_COMMENT ; 
-    } else if (line[0]=='[' && line[len-1]==']') {
-        /* Section name */
-        sscanf(line, "[%[^]]", section);
-        strcpy(section, strstrip(section));
-        strcpy(section, strlwc(section));
-        sta = LINE_SECTION ;
-    } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
-           ||  sscanf (line, "%[^=] = '%[^\']'",   key, value) == 2
-           ||  sscanf (line, "%[^=] = %[^;#]",     key, value) == 2) {
-        /* Usual key=value, with or without comments */
-        strcpy(key, strstrip(key));
-        strcpy(key, strlwc(key));
-        strcpy(value, strstrip(value));
-        /*
-         * sscanf cannot handle '' or "" as empty values
-         * this is done here
-         */
-        if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
-            value[0]=0 ;
-        }
-        sta = LINE_VALUE ;
-    } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
-           ||  sscanf(line, "%[^=] %[=]", key, value) == 2) {
-        /*
-         * Special cases:
-         * key=
-         * key=;
-         * key=#
-         */
-        strcpy(key, strstrip(key));
-        strcpy(key, strlwc(key));
-        value[0]=0 ;
-        sta = LINE_VALUE ;
-    } else {
-        /* Generate syntax error */
-        sta = LINE_ERROR ;
-    }
-    return sta ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Parse an ini file and return an allocated dictionary object
-  @param    ininame Name of the ini file to read.
-  @return   Pointer to newly allocated dictionary
-
-  This is the parser for ini files. This function is called, providing
-  the name of the file to be read. It returns a dictionary object that
-  should not be accessed directly, but through accessor functions
-  instead.
-
-  The returned dictionary must be freed using iniparser_freedict().
- */
-/*--------------------------------------------------------------------------*/
-dictionary * iniparser_load(const char * ininame)
-{
-    FILE * in ;
-
-    char line    [ASCIILINESZ+1] ;
-    char section [ASCIILINESZ+1] ;
-    char key     [ASCIILINESZ+1] ;
-    char tmp     [ASCIILINESZ+1] ;
-    char val     [ASCIILINESZ+1] ;
-
-    int  last=0 ;
-    int  len ;
-    int  lineno=0 ;
-    int  errs=0;
-
-    dictionary * dict ;
-
-    if ((in=fopen(ininame, "r"))==NULL) {
-        fprintf(stderr, "iniparser: cannot open %s\n", ininame);
-        return NULL ;
-    }
-
-    dict = dictionary_new(0) ;
-    if (!dict) {
-        fclose(in);
-        return NULL ;
-    }
-
-    memset(line,    0, ASCIILINESZ);
-    memset(section, 0, ASCIILINESZ);
-    memset(key,     0, ASCIILINESZ);
-    memset(val,     0, ASCIILINESZ);
-    last=0 ;
-
-    while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
-        lineno++ ;
-        len = (int)strlen(line)-1;
-        /* Safety check against buffer overflows */
-        if (line[len]!='\n') {
-            fprintf(stderr,
-                    "iniparser: input line too long in %s (%d)\n",
-                    ininame,
-                    lineno);
-            dictionary_del(dict);
-            fclose(in);
-            return NULL ;
-        }
-        /* Get rid of \n and spaces at end of line */
-        while ((len>=0) &&
-                ((line[len]=='\n') || (isspace(line[len])))) {
-            line[len]=0 ;
-            len-- ;
-        }
-        /* Detect multi-line */
-        if (line[len]=='\\') {
-            /* Multi-line value */
-            last=len ;
-            continue ;
-        } else {
-            last=0 ;
-        }
-        switch (iniparser_line(line, section, key, val)) {
-            case LINE_EMPTY:
-            case LINE_COMMENT:
-            break ;
-
-            case LINE_SECTION:
-            errs = dictionary_set(dict, section, NULL);
-            break ;
-
-            case LINE_VALUE:
-            sprintf(tmp, "%s:%s", section, key);
-            errs = dictionary_set(dict, tmp, val) ;
-            break ;
-
-            case LINE_ERROR:
-            fprintf(stderr, "iniparser: syntax error in %s (%d):\n",
-                    ininame,
-                    lineno);
-            fprintf(stderr, "-> %s\n", line);
-            errs++ ;
-            break;
-
-            default:
-            break ;
-        }
-        memset(line, 0, ASCIILINESZ);
-        last=0;
-        if (errs<0) {
-            fprintf(stderr, "iniparser: memory allocation failure\n");
-            break ;
-        }
-    }
-    if (errs) {
-        dictionary_del(dict);
-        dict = NULL ;
-    }
-    fclose(in);
-    return dict ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Free all memory associated to an ini dictionary
-  @param    d Dictionary to free
-  @return   void
-
-  Free all memory associated to an ini dictionary.
-  It is mandatory to call this function before the dictionary object
-  gets out of the current context.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_freedict(dictionary * d)
-{
-    dictionary_del(d);
-}
-
-/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/ubi-utils/new-utils/src/libmtd.c b/ubi-utils/new-utils/src/libmtd.c
deleted file mode 100644
index b60ddbd..0000000
--- a/ubi-utils/new-utils/src/libmtd.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * 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.
- *
- * Author: Artem Bityutskiy
- *
- * MTD library.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <mtd/mtd-user.h>
-#include <libmtd.h>
-#include "common.h"
-
-#define PROGRAM_NAME "libmtd"
-#define MTD_DEV_MAJOR 90
-
-/**
- * mtd_get_info - get information about an MTD device.
- * @node: name of the MTD device node
- * @mtd: the MTD device information is returned here
- *
- * This function gets information about MTD device defined by the @node device
- * node file and saves this information in the @mtd object. Returns %0 in case
- * of success and %-1 in case of failure.
- */
-int mtd_get_info(const char *node, struct mtd_info *mtd)
-{
-	struct stat st;
-	struct mtd_info_user ui;
-	int ret;
-	loff_t offs = 0;
-
-	if (stat(node, &st))
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	if (!S_ISCHR(st.st_mode)) {
-		errno = EINVAL;
-		return errmsg("\"%s\" is not a character device", node);
-	}
-
-	mtd->major = major(st.st_rdev);
-	mtd->minor = minor(st.st_rdev);
-
-	if (mtd->major != MTD_DEV_MAJOR) {
-		errno = EINVAL;
-		return errmsg("\"%s\" has major number %d, MTD devices have "
-			      "major %d", node, mtd->major, MTD_DEV_MAJOR);
-	}
-
-	mtd->num = mtd->minor / 2;
-	mtd->rdonly = mtd->minor & 1;
-
-	mtd->fd = open(node, O_RDWR);
-	if (mtd->fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	if (ioctl(mtd->fd, MEMGETINFO, &ui)) {
-		sys_errmsg("MEMGETINFO ioctl request failed");
-		goto out_close;
-	}
-
-	ret = ioctl(mtd->fd, MEMGETBADBLOCK, &offs);
-	if (ret == -1) {
-		if (errno != EOPNOTSUPP) {
-			sys_errmsg("MEMGETBADBLOCK ioctl failed");
-			goto out_close;
-		}
-		errno = 0;
-		mtd->allows_bb = 0;
-	} else
-		mtd->allows_bb = 1;
-
-	mtd->type = ui.type;
-	mtd->size = ui.size;
-	mtd->eb_size = ui.erasesize;
-	mtd->min_io_size = ui.writesize;
-
-	if (mtd->min_io_size <= 0) {
-		errmsg("mtd%d (%s) has insane min. I/O unit size %d",
-		       mtd->num, node, mtd->min_io_size);
-		goto out_close;
-	}
-	if (mtd->eb_size <= 0 || mtd->eb_size < mtd->min_io_size) {
-		errmsg("mtd%d (%s) has insane eraseblock size %d",
-		       mtd->num, node, mtd->eb_size);
-		goto out_close;
-	}
-	if (mtd->size <= 0 || mtd->size < mtd->eb_size) {
-		errmsg("mtd%d (%s) has insane size %lld",
-		       mtd->num, node, mtd->size);
-		goto out_close;
-	}
-	mtd->eb_cnt = mtd->size / mtd->eb_size;
-
-	switch(mtd->type) {
-	case MTD_ABSENT:
-		errmsg("mtd%d (%s) is removable and is not present",
-		       mtd->num, node);
-		goto out_close;
-	case MTD_RAM:
-		mtd->type_str = "RAM-based";
-		break;
-	case MTD_ROM:
-		mtd->type_str = "ROM";
-		break;
-	case MTD_NORFLASH:
-		mtd->type_str = "NOR";
-		break;
-	case MTD_NANDFLASH:
-		mtd->type_str = "NAND";
-		break;
-	case MTD_DATAFLASH:
-		mtd->type_str = "DataFlash";
-		break;
-	case MTD_UBIVOLUME:
-		mtd->type_str = "UBI-emulated MTD";
-		break;
-	default:
-		mtd->type_str = "Unknown flash type";
-		break;
-	}
-
-	if (!(ui.flags & MTD_WRITEABLE))
-		mtd->rdonly = 1;
-
-	return 0;
-
-out_close:
-	close(mtd->fd);
-	return -1;
-}
-
-/**
- * mtd_erase - erase an eraseblock.
- * @mtd: MTD device description object
- * @eb: eraseblock to erase
- *
- * This function erases the eraseblock and returns %0 in case of success and
- * %-1 in case of failure.
- */
-int mtd_erase(const struct mtd_info *mtd, int eb)
-{
-	struct erase_info_user ei;
-
-	ei.start = eb * mtd->eb_size;;
-	ei.length = mtd->eb_size;
-	return ioctl(mtd->fd, MEMERASE, &ei);
-}
-
-/**
- * mtd_is_bad - check if eraseblock is bad.
- * @mtd: MTD device description object
- * @eb: eraseblock to check
- *
- * This function checks if eraseblock @eb is bad. Returns %0 if not, %1 if yes,
- * and %-1 in case of failure.
- */
-int mtd_is_bad(const struct mtd_info *mtd, int eb)
-{
-	int ret;
-	loff_t seek;
-
-	if (eb < 0 || eb >= mtd->eb_cnt) {
-		errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks",
-		       eb, mtd->num, mtd->eb_cnt);
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (!mtd->allows_bb)
-		return 0;
-
-	seek = (loff_t)eb * mtd->eb_size;
-	ret = ioctl(mtd->fd, MEMGETBADBLOCK, &seek);
-	if (ret == -1) {
-		sys_errmsg("MEMGETBADBLOCK ioctl failed for "
-			   "eraseblock %d (mtd%d)", eb, mtd->num);
-		return -1;
-	}
-
-	return ret;
-}
-
-/**
- * mtd_read - read data from an MTD device.
- * @mtd: MTD device description object
- * @eb: eraseblock to read from
- * @offs: offset withing the eraseblock to read from
- * @buf: buffer to read data to
- * @len: how many bytes to read
- *
- * This function reads @len bytes of data from eraseblock @eb and offset @offs
- * of the MTD device defined by @mtd and stores the read data at buffer @buf.
- * Returns %0 in case of success and %-1 in case of failure.
- */
-int mtd_read(const struct mtd_info *mtd, int eb, int offs, void *buf, int len)
-{
-	int ret, rd = 0;
-	off_t seek;
-
-	if (eb < 0 || eb >= mtd->eb_cnt) {
-		errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks",
-		       eb, mtd->num, mtd->eb_cnt);
-		errno = EINVAL;
-		return -1;
-	}
-	if (offs < 0 || offs + len > mtd->eb_size) {
-		errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d",
-		       offs, len, mtd->num, mtd->eb_size);
-		errno = EINVAL;
-		return -1;
-	}
-
-	/* Seek to the beginning of the eraseblock */
-	seek = (off_t)eb * mtd->eb_size + offs;
-	if (lseek(mtd->fd, seek, SEEK_SET) != seek) {
-		sys_errmsg("cannot seek mtd%d to offset %llu",
-			   mtd->num, (unsigned long long)seek);
-		return -1;
-	}
-
-	while (rd < len) {
-		ret = read(mtd->fd, buf, len);
-		if (ret < 0) {
-			sys_errmsg("cannot read %d bytes from mtd%d (eraseblock %d, offset %d)",
-				   len, mtd->num, eb, offs);
-			return -1;
-		}
-		rd += ret;
-	}
-
-	return 0;
-}
-
-/**
- * mtd_write - write data to an MTD device.
- * @mtd: MTD device description object
- * @eb: eraseblock to write to
- * @offs: offset withing the eraseblock to write to
- * @buf: buffer to write
- * @len: how many bytes to write
- *
- * This function writes @len bytes of data to eraseblock @eb and offset @offs
- * of the MTD device defined by @mtd. Returns %0 in case of success and %-1 in
- * case of failure.
- */
-int mtd_write(const struct mtd_info *mtd, int eb, int offs, void *buf, int len)
-{
-	int ret;
-	off_t seek;
-
-	if (eb < 0 || eb >= mtd->eb_cnt) {
-		errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks",
-		       eb, mtd->num, mtd->eb_cnt);
-		errno = EINVAL;
-		return -1;
-	}
-	if (offs < 0 || offs + len > mtd->eb_size) {
-		errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d",
-		       offs, len, mtd->num, mtd->eb_size);
-		errno = EINVAL;
-		return -1;
-	}
-#if 0
-	if (offs % mtd->subpage_size) {
-		errmsg("write offset %d is not aligned to mtd%d min. I/O size %d",
-		       offs, mtd->num, mtd->subpage_size);
-		errno = EINVAL;
-		return -1;
-	}
-	if (len % mtd->subpage_size) {
-		errmsg("write length %d is not aligned to mtd%d min. I/O size %d",
-		       len, mtd->num, mtd->subpage_size);
-		errno = EINVAL;
-		return -1;
-	}
-#endif
-
-	/* Seek to the beginning of the eraseblock */
-	seek = (off_t)eb * mtd->eb_size + offs;
-	if (lseek(mtd->fd, seek, SEEK_SET) != seek) {
-		sys_errmsg("cannot seek mtd%d to offset %llu",
-			   mtd->num, (unsigned long long)seek);
-		return -1;
-	}
-
-	ret = write(mtd->fd, buf, len);
-	if (ret != len) {
-		sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)",
-			   len, mtd->num, eb, offs);
-		return -1;
-	}
-
-	return 0;
-}
diff --git a/ubi-utils/new-utils/src/libscan.c b/ubi-utils/new-utils/src/libscan.c
deleted file mode 100644
index dc1f083..0000000
--- a/ubi-utils/new-utils/src/libscan.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * 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.
- *
- * Author: Artem Bityutskiy
- *
- * UBI scanning library.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdint.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include <mtd_swab.h>
-#include <mtd/ubi-media.h>
-#include <mtd/mtd-user.h>
-#include <libmtd.h>
-#include <libscan.h>
-#include "common.h"
-#include "crc32.h"
-
-#define PROGRAM_NAME "libscan"
-
-static int all_ff(const void *buf, int len)
-{
-	int i;
-	const uint8_t *p = buf;
-
-	for (i = 0; i < len; i++)
-		if (p[i] != 0xFF)
-			return 0;
-	return 1;
-}
-
-int ubi_scan(struct mtd_info *mtd, struct ubi_scan_info **info, int verbose)
-{
-	int eb, v = (verbose == 2), pr = (verbose == 1);
-	struct ubi_scan_info *si;
-	unsigned long long sum = 0;
-
-	si = calloc(1, sizeof(struct ubi_scan_info));
-	if (!si)
-		return sys_errmsg("cannot allocate %zd bytes of memory",
-				  sizeof(struct ubi_scan_info));
-
-	si->ec = calloc(mtd->eb_cnt, sizeof(uint32_t));
-	if (!si->ec) {
-		sys_errmsg("cannot allocate %zd bytes of memory",
-			   sizeof(struct ubi_scan_info));
-		goto out_si;
-	}
-
-	si->vid_hdr_offs = si->data_offs = -1;
-
-	verbose(v, "start scanning eraseblocks 0-%d", mtd->eb_cnt);
-	for (eb = 0; eb < mtd->eb_cnt; eb++) {
-		int ret;
-		uint32_t crc;
-		struct ubi_ec_hdr hdr;
-		unsigned long long ec;
-
-		if (v) {
-			normsg_cont("scanning eraseblock %d", eb);
-			fflush(stdout);
-		}
-		if (pr) {
-			printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2lld %% complete  ",
-			       eb, (long long)(eb + 1) * 100 / mtd->eb_cnt);
-			fflush(stdout);
-		}
-
-		ret = mtd_is_bad(mtd, eb);
-		if (ret == -1)
-			goto out_ec;
-		if (ret) {
-			si->bad_cnt += 1;
-			si->ec[eb] = EB_BAD;
-			if (v)
-				printf(": bad\n");
-			continue;
-		}
-
-		ret = mtd_read(mtd, eb, 0, &hdr, sizeof(struct ubi_ec_hdr));;
-		if (ret < 0)
-			goto out_ec;
-
-		/* Check the EC header */
-		if (be32_to_cpu(hdr.magic) != UBI_EC_HDR_MAGIC) {
-			if (all_ff(&hdr, sizeof(struct ubi_ec_hdr))) {
-				si->empty_cnt += 1;
-				si->ec[eb] = EB_EMPTY;
-				if (v)
-					printf(": empty\n");
-			} else {
-				si->alien_cnt += 1;
-				si->ec[eb] = EB_ALIEN;
-				if (v)
-					printf(": alien\n");
-			}
-			continue;
-		}
-
-		crc = crc32(UBI_CRC32_INIT, &hdr, UBI_EC_HDR_SIZE_CRC);
-		if (be32_to_cpu(hdr.hdr_crc) != crc) {
-			si->corrupted_cnt += 1;
-			si->ec[eb] = EB_CORRUPTED;
-			if (v)
-				printf(": bad CRC %#08x, should be %#08x\n",
-				       crc, be32_to_cpu(hdr.hdr_crc));
-			continue;
-		}
-
-		ec = be64_to_cpu(hdr.ec);
-		if (ec > EC_MAX) {
-			if (pr)
-				printf("\n");
-			errmsg("erase counter in EB %d is %llu, while this "
-			       "program expects them to be less than %u",
-			       eb, ec, EC_MAX);
-			goto out_ec;
-		}
-
-		if (si->vid_hdr_offs == -1) {
-			si->vid_hdr_offs = be32_to_cpu(hdr.vid_hdr_offset);
-			si->data_offs = be32_to_cpu(hdr.data_offset);
-			if (si->data_offs % mtd->min_io_size) {
-				if (pr)
-					printf("\n");
-				if (v)
-					printf(": corrupted because of the below\n");
-				warnmsg("bad data offset %d at eraseblock %d (n"
-					"of multiple of min. I/O unit size %d)",
-					si->data_offs, eb, mtd->min_io_size);
-				warnmsg("treat eraseblock %d as corrupted", eb);
-				si->corrupted_cnt += 1;
-				si->ec[eb] = EB_CORRUPTED;
-				continue;
-
-			}
-		} else {
-			if ((int)be32_to_cpu(hdr.vid_hdr_offset) != si->vid_hdr_offs) {
-				if (pr)
-					printf("\n");
-				if (v)
-					printf(": corrupted because of the below\n");
-				warnmsg("inconsistent VID header offset: was "
-					"%d, but is %d in eraseblock %d",
-					si->vid_hdr_offs,
-					be32_to_cpu(hdr.vid_hdr_offset), eb);
-				warnmsg("treat eraseblock %d as corrupted", eb);
-				si->corrupted_cnt += 1;
-				si->ec[eb] = EB_CORRUPTED;
-				continue;
-			}
-			if ((int)be32_to_cpu(hdr.data_offset) != si->data_offs) {
-				if (pr)
-					printf("\n");
-				if (v)
-					printf(": corrupted because of the below\n");
-				warnmsg("inconsistent data offset: was %d, but"
-					" is %d in eraseblock %d",
-					si->data_offs,
-					be32_to_cpu(hdr.data_offset), eb);
-				warnmsg("treat eraseblock %d as corrupted", eb);
-				si->corrupted_cnt += 1;
-				si->ec[eb] = EB_CORRUPTED;
-				continue;
-			}
-		}
-
-		si->ok_cnt += 1;
-		si->ec[eb] = ec;
-		if (v)
-			printf(": OK, erase counter %u\n", si->ec[eb]);
-	}
-
-	if (si->ok_cnt != 0) {
-		/* Calculate mean erase counter */
-		for (eb = 0; eb < mtd->eb_cnt; eb++) {
-			if (si->ec[eb] > EC_MAX)
-				continue;
-			sum += si->ec[eb];
-		}
-		si->mean_ec = sum / si->ok_cnt;
-	}
-
-	si->good_cnt = mtd->eb_cnt - si->bad_cnt;
-	verbose(v, "finished, mean EC %lld, %d OK, %d corrupted, %d empty, %d "
-		"alien, bad %d", si->mean_ec, si->ok_cnt, si->corrupted_cnt,
-		si->empty_cnt, si->alien_cnt, si->bad_cnt);
-
-	*info = si;
-	if (pr)
-		printf("\n");
-	return 0;
-
-out_ec:
-	free(si->ec);
-out_si:
-	free(si);
-	*info = NULL;
-	return -1;
-}
-
-void ubi_scan_free(struct ubi_scan_info *si)
-{
-	free(si->ec);
-	free(si);
-}
diff --git a/ubi-utils/new-utils/src/libubi.c b/ubi-utils/new-utils/src/libubi.c
deleted file mode 100644
index 1aa66d8..0000000
--- a/ubi-utils/new-utils/src/libubi.c
+++ /dev/null
@@ -1,1206 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Artem Bityutskiy
- *
- * UBI (Unsorted Block Images) library.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include "libubi.h"
-#include "libubi_int.h"
-#include "common.h"
-
-#define PROGRAM_NAME "libubi"
-
-/**
- * mkpath - compose full path from 2 given components.
- * @path: the first component
- * @name: the second component
- *
- * This function returns the resulting path in case of success and %NULL in
- * case of failure.
- */
-static char *mkpath(const char *path, const char *name)
-{
-	char *n;
-	int len1 = strlen(path);
-	int len2 = strlen(name);
-
-	n = malloc(len1 + len2 + 2);
-	if (!n) {
-		sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2);
-		return NULL;
-	}
-
-	memcpy(n, path, len1);
-	if (n[len1 - 1] != '/')
-		n[len1++] = '/';
-
-	memcpy(n + len1, name, len2 + 1);
-	return n;
-}
-
-/**
- * read_positive_ll - read a positive 'long long' value from a file.
- * @file: the file to read from
- * @value: the result is stored here
- *
- * This function reads file @file and interprets its contents as a positive
- * 'long long' integer. If this is not true, it fails with %EINVAL error code.
- * Returns %0 in case of success and %-1 in case of failure.
- */
-static int read_positive_ll(const char *file, long long *value)
-{
-	int fd, rd;
-	char buf[50];
-
-	fd = open(file, O_RDONLY);
-	if (fd == -1)
-		return -1;
-
-	rd = read(fd, buf, 50);
-	if (rd == -1) {
-		sys_errmsg("cannot read \"%s\"", file);
-		goto out_error;
-	}
-	if (rd == 50) {
-		errmsg("contents of \"%s\" is too long", file);
-		errno = EINVAL;
-		goto out_error;
-	}
-
-	if (sscanf(buf, "%lld\n", value) != 1) {
-		/* This must be a UBI bug */
-		errmsg("cannot read integer from \"%s\"\n", file);
-		errno = EINVAL;
-		goto out_error;
-	}
-
-	if (*value < 0) {
-		errmsg("negative value %lld in \"%s\"", *value, file);
-		errno = EINVAL;
-		goto out_error;
-	}
-
-	if (close(fd))
-		return sys_errmsg("close failed on \"%s\"", file);
-
-	return 0;
-
-out_error:
-	close(fd);
-	return -1;
-}
-
-/**
- * read_positive_int - read a positive 'int' value from a file.
- * @file: the file to read from
- * @value: the result is stored here
- *
- * This function is the same as 'read_positive_ll()', but it reads an 'int'
- * value, not 'long long'.
- */
-static int read_positive_int(const char *file, int *value)
-{
-	long long res;
-
-	if (read_positive_ll(file, &res))
-		return -1;
-
-	/* Make sure the value is not too big */
-	if (res > INT_MAX) {
-		errmsg("value %lld read from file \"%s\" is out of range",
-		       res, file);
-		errno = EINVAL;
-		return -1;
-	}
-
-	*value = res;
-	return 0;
-}
-
-/**
- * read_data - read data from a file.
- * @file: the file to read from
- * @buf: the buffer to read to
- * @buf_len: buffer length
- *
- * This function returns number of read bytes in case of success and %-1 in
- * case of failure. Note, if the file contains more then @buf_len bytes of
- * date, this function fails with %EINVAL error code.
- */
-static int read_data(const char *file, void *buf, int buf_len)
-{
-	int fd, rd, tmp, tmp1;
-
-	fd = open(file, O_RDONLY);
-	if (fd == -1)
-		return -1;
-
-	rd = read(fd, buf, buf_len);
-	if (rd == -1) {
-		sys_errmsg("cannot read \"%s\"", file);
-		goto out_error;
-	}
-
-	/* Make sure all data is read */
-	tmp1 = read(fd, &tmp, 1);
-	if (tmp1 == 1) {
-		sys_errmsg("cannot read \"%s\"", file);
-		goto out_error;
-	}
-	if (tmp1) {
-		errmsg("file \"%s\" contains too much data (> %d bytes)",
-		       file, buf_len);
-		errno = EINVAL;
-		goto out_error;
-	}
-
-	if (close(fd)) {
-		sys_errmsg("close failed on \"%s\"", file);
-		return -1;
-	}
-
-	return rd;
-
-out_error:
-	close(fd);
-	return -1;
-}
-
-/**
- * read_major - read major and minor numbers from a file.
- * @file: name of the file to read from
- * @major: major number is returned here
- * @minor: minor number is returned here
- *
- * This function returns % in case of succes, and %-1 in case of failure.
- */
-static int read_major(const char *file, int *major, int *minor)
-{
-	int ret;
-	char buf[50];
-
-	ret = read_data(file, buf, 50);
-	if (ret < 0)
-		return ret;
-
-	ret = sscanf(buf, "%d:%d\n", major, minor);
-	if (ret != 2) {
-		errno = EINVAL;
-		return errmsg("\"%s\" does not have major:minor format", file);
-	}
-
-	if (*major < 0 || *minor < 0) {
-		errno = EINVAL;
-		return errmsg("bad major:minor %d:%d in \"%s\"",
-			      *major, *minor, file);
-	}
-
-	return 0;
-}
-
-/**
- * dev_read_int - read a positive 'int' value from an UBI device sysfs file.
- * @patt: file pattern to read from
- * @dev_num:  UBI device number
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_int(const char *patt, int dev_num, int *value)
-{
-	char file[strlen(patt) + 50];
-
-	sprintf(file, patt, dev_num);
-	return read_positive_int(file, value);
-}
-
-/**
- * vol_read_int - read a positive 'int' value from an UBI volume sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
-{
-	char file[strlen(patt) + 100];
-
-	sprintf(file, patt, dev_num, vol_id);
-	return read_positive_int(file, value);
-}
-
-/**
- * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_ll(const char *patt, int dev_num, long long *value)
-{
-	char file[strlen(patt) + 50];
-
-	sprintf(file, patt, dev_num);
-	return read_positive_ll(file, value);
-}
-
-/**
- * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_ll(const char *patt, int dev_num, int vol_id,
-		       long long *value)
-{
-	char file[strlen(patt) + 100];
-
-	sprintf(file, patt, dev_num, vol_id);
-	return read_positive_ll(file, value);
-}
-
-/**
- * vol_read_data - read data from an UBI volume's sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @buf: buffer to read to
- * @buf_len: buffer length
- *
- * This function returns number of read bytes in case of success and %-1 in
- * case of failure.
- */
-static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
-			 int buf_len)
-{
-	char file[strlen(patt) + 100];
-
-	sprintf(file, patt, dev_num, vol_id);
-	return read_data(file, buf, buf_len);
-}
-
-/**
- * dev_get_major - get major and minor numbers of an UBI device.
- * @lib: libubi descriptor
- * @dev_num: UBI device number
- * @major: major number is returned here
- * @minor: minor number is returned here
- *
- * This function returns zero in case of succes and %-1 in case of failure.
- */
-static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor)
-{
-	char file[strlen(lib->dev_dev) + 50];
-
-	sprintf(file, lib->dev_dev, dev_num);
-	return read_major(file, major, minor);
-}
-
-/**
- * vol_get_major - get major and minor numbers of an UBI volume.
- * @lib: libubi descriptor
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @major: major number is returned here
- * @minor: minor number is returned here
- *
- * This function returns zero in case of succes and %-1 in case of failure.
- */
-static int vol_get_major(struct libubi *lib, int dev_num, int vol_id,
-			 int *major, int *minor)
-{
-	char file[strlen(lib->vol_dev) + 100];
-
-	sprintf(file, lib->vol_dev, dev_num, vol_id);
-	return read_major(file, major, minor);
-}
-
-/**
- * vol_node2nums - find UBI device number and volume ID by volume device node
- *                 file.
- * @lib: UBI library descriptor
- * @node: UBI character device node name
- * @dev_num: UBI device number is returned here
- * @vol_id: volume ID is returned hers
- *
- * This function returns zero in case of succes and %-1 in case of failure.
- */
-static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,
-			 int *vol_id)
-{
-	struct stat st;
-	struct ubi_info info;
-	int i, fd, major, minor;
-	char file[strlen(lib->ubi_vol) + 100];
-
-	if (stat(node, &st))
-		return sys_errmsg("cannot get information about \"%s\"",
-				  node);
-
-	if (!S_ISCHR(st.st_mode)) {
-		errno = EINVAL;
-		return errmsg("\"%s\" is not a character device", node);
-	}
-
-	major = major(st.st_rdev);
-	minor = minor(st.st_rdev);
-
-	if (minor == 0) {
-		errno = EINVAL;
-		return errmsg("\"%s\" is not a volume character device", node);
-	}
-
-	if (ubi_get_info((libubi_t *)lib, &info))
-		return -1;
-
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		int major1, minor1, ret;
-
-		ret = dev_get_major(lib, i, &major1, &minor1);
-		if (ret) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (major1 == major)
-			break;
-	}
-
-	if (i > info.highest_dev_num) {
-		errno = ENODEV;
-		return -1;
-	}
-
-	/* Make sure this UBI volume exists */
-	sprintf(file, lib->ubi_vol, i, minor - 1);
-	fd = open(file, O_RDONLY);
-	if (fd == -1) {
-		errno = ENODEV;
-		return -1;
-	}
-
-	*dev_num = i;
-	*vol_id = minor - 1;
-	errno = 0;
-	return 0;
-}
-
-/**
- * dev_node2num - find UBI device number by its character device node.
- * @lib: UBI library descriptor
- * @node: UBI character device node name
- *
- * This function returns positive UBI device number in case of success and %-1
- * in case of failure.
- */
-static int dev_node2num(struct libubi *lib, const char *node, int *dev_num)
-{
-	struct stat st;
-	struct ubi_info info;
-	int i, major, minor;
-
-	if (stat(node, &st))
-		return sys_errmsg("cannot get information about \"%s\"",
-				  node);
-
-	if (!S_ISCHR(st.st_mode)) {
-		errno = EINVAL;
-		return errmsg("\"%s\" is not a character device", node);
-	}
-
-	major = major(st.st_rdev);
-	minor = minor(st.st_rdev);
-
-	if (minor != 0) {
-		errno = EINVAL;
-		return errmsg("\"%s\" is not an UBI character device", node);
-	}
-
-	if (ubi_get_info((libubi_t *)lib, &info))
-		return -1;
-
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		int major1, minor1, ret;
-
-		ret = dev_get_major(lib, i, &major1, &minor1);
-		if (ret) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (major1 == major) {
-			if (minor1 != 0) {
-				errmsg("UBI character device minor number is "
-				       "%d, but must be 0", minor1);
-				errno = EINVAL;
-				return -1;
-			}
-			errno = 0;
-			*dev_num = i;
-			return 0;
-		}
-	}
-
-	errno = ENODEV;
-	return -1;
-}
-
-int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num)
-{
-	struct ubi_info info;
-	int i, ret, mtd_num1;
-	struct libubi *lib = desc;
-
-	if (ubi_get_info(desc, &info))
-		return -1;
-
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1);
-		if (ret) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (mtd_num1 == mtd_num) {
-			errno = 0;
-			*dev_num = i;
-			return 0;
-		}
-	}
-
-	errno = 0;
-	return -1;
-}
-
-libubi_t libubi_open(int required)
-{
-	int fd, version;
-	struct libubi *lib;
-
-	lib = calloc(1, sizeof(struct libubi));
-	if (!lib)
-		return NULL;
-
-	/* TODO: this must be discovered instead */
-	lib->sysfs = strdup("/sys");
-	if (!lib->sysfs)
-		goto out_error;
-
-	lib->sysfs_ctrl = mkpath(lib->sysfs, SYSFS_CTRL);
-	if (!lib->sysfs_ctrl)
-		goto out_error;
-
-	lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV);
-	if (!lib->ctrl_dev)
-		goto out_error;
-
-	lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI);
-	if (!lib->sysfs_ubi)
-		goto out_error;
-
-	/* Make sure UBI is present */
-	fd = open(lib->sysfs_ubi, O_RDONLY);
-	if (fd == -1) {
-		if (required)
-			errmsg("cannot open \"%s\", UBI does not seem to "
-			       "exist in system", lib->sysfs_ubi);
-		goto out_error;
-	}
-
-	if (close(fd)) {
-		sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi);
-		goto out_error;
-	}
-
-	lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);
-	if (!lib->ubi_dev)
-		goto out_error;
-
-	lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);
-	if (!lib->ubi_version)
-		goto out_error;
-
-	lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);
-	if (!lib->dev_dev)
-		goto out_error;
-
-	lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);
-	if (!lib->dev_avail_ebs)
-		goto out_error;
-
-	lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);
-	if (!lib->dev_total_ebs)
-		goto out_error;
-
-	lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);
-	if (!lib->dev_bad_count)
-		goto out_error;
-
-	lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);
-	if (!lib->dev_eb_size)
-		goto out_error;
-
-	lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC);
-	if (!lib->dev_max_ec)
-		goto out_error;
-
-	lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD);
-	if (!lib->dev_bad_rsvd)
-		goto out_error;
-
-	lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS);
-	if (!lib->dev_max_vols)
-		goto out_error;
-
-	lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE);
-	if (!lib->dev_min_io_size)
-		goto out_error;
-
-	lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM);
-	if (!lib->dev_mtd_num)
-		goto out_error;
-
-	lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT);
-	if (!lib->ubi_vol)
-		goto out_error;
-
-	lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE);
-	if (!lib->vol_type)
-		goto out_error;
-
-	lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV);
-	if (!lib->vol_dev)
-		goto out_error;
-
-	lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT);
-	if (!lib->vol_alignment)
-		goto out_error;
-
-	lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES);
-	if (!lib->vol_data_bytes)
-		goto out_error;
-
-	lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS);
-	if (!lib->vol_rsvd_ebs)
-		goto out_error;
-
-	lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE);
-	if (!lib->vol_eb_size)
-		goto out_error;
-
-	lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED);
-	if (!lib->vol_corrupted)
-		goto out_error;
-
-	lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME);
-	if (!lib->vol_name)
-		goto out_error;
-
-	if (read_positive_int(lib->ubi_version, &version))
-		goto out_error;
-	if (version != LIBUBI_UBI_VERSION) {
-		errmsg("this library was made for UBI version %d, but UBI "
-		       "version %d is detected\n", LIBUBI_UBI_VERSION, version);
-		goto out_error;
-	}
-
-	return lib;
-
-out_error:
-	libubi_close((libubi_t)lib);
-	return NULL;
-}
-
-void libubi_close(libubi_t desc)
-{
-	struct libubi *lib = (struct libubi *)desc;
-
-	free(lib->vol_name);
-	free(lib->vol_corrupted);
-	free(lib->vol_eb_size);
-	free(lib->vol_rsvd_ebs);
-	free(lib->vol_data_bytes);
-	free(lib->vol_alignment);
-	free(lib->vol_dev);
-	free(lib->vol_type);
-	free(lib->ubi_vol);
-	free(lib->dev_mtd_num);
-	free(lib->dev_min_io_size);
-	free(lib->dev_max_vols);
-	free(lib->dev_bad_rsvd);
-	free(lib->dev_max_ec);
-	free(lib->dev_eb_size);
-	free(lib->dev_bad_count);
-	free(lib->dev_total_ebs);
-	free(lib->dev_avail_ebs);
-	free(lib->dev_dev);
-	free(lib->ubi_version);
-	free(lib->ubi_dev);
-	free(lib->sysfs_ubi);
-	free(lib->ctrl_dev);
-	free(lib->sysfs_ctrl);
-	free(lib->sysfs);
-	free(lib);
-}
-
-int ubi_attach_mtd(libubi_t desc, const char *node,
-		   struct ubi_attach_request *req)
-{
-	int fd, ret;
-	struct ubi_attach_req r;
-
-	memset(&r, sizeof(struct ubi_attach_req), '\0');
-
-	desc = desc;
-	r.ubi_num = req->dev_num;
-	r.mtd_num = req->mtd_num;
-	r.vid_hdr_offset = req->vid_hdr_offset;
-
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	ret = ioctl(fd, UBI_IOCATT, &r);
-	close(fd);
-	if (ret == -1)
-		return -1;
-
-	req->dev_num = r.ubi_num;
-
-#ifdef UDEV_SETTLE_HACK
-	if (system("udevsettle") == -1)
-		return -1;
-#endif
-
-	return ret;
-}
-
-int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
-{
-	int ret, ubi_dev;
-
-	ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev);
-	if (ret == -1) {
-		errno = ENODEV;
-		return ret;
-	}
-
-	return ubi_remove_dev(desc, node, ubi_dev);
-}
-
-int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
-{
-	int fd, ret;
-
-	desc = desc;
-
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-	ret = ioctl(fd, UBI_IOCDET, &ubi_dev);
-	if (ret == -1)
-		goto out_close;
-
-#ifdef UDEV_SETTLE_HACK
-	if (system("udevsettle") == -1)
-		return -1;
-#endif
-
-out_close:
-	close(fd);
-	return ret;
-}
-
-int ubi_node_type(libubi_t desc, const char *node)
-{
-	struct stat st;
-	struct ubi_info info;
-	int i, fd, major, minor;
-	struct libubi *lib = (struct libubi *)desc;
-	char file[strlen(lib->ubi_vol) + 100];
-
-	if (stat(node, &st))
-		return sys_errmsg("cannot get information about \"%s\"",
-				  node);
-
-	if (!S_ISCHR(st.st_mode)) {
-		errmsg("\"%s\" is not a character device", node);
-		errno = EINVAL;
-		return -1;
-	}
-
-	major = major(st.st_rdev);
-	minor = minor(st.st_rdev);
-
-	if (ubi_get_info((libubi_t *)lib, &info))
-		return -1;
-
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		int major1, minor1, ret;
-
-		ret = dev_get_major(lib, i, &major1, &minor1);
-		if (ret) {
-			if (errno == ENOENT)
-				continue;
-			if (!errno)
-				goto out_not_ubi;
-			return -1;
-		}
-
-		if (major1 == major)
-			break;
-	}
-
-	if (i > info.highest_dev_num)
-		goto out_not_ubi;
-
-	if (minor == 0)
-		return 1;
-
-	/* This is supposdely an UBI volume device node */
-	sprintf(file, lib->ubi_vol, i, minor - 1);
-	fd = open(file, O_RDONLY);
-	if (fd == -1) {
-		sys_errmsg("cannot open \"%s\"", node);
-		return -1;
-	}
-
-	return 2;
-
-out_not_ubi:
-	errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to "
-	       "any UBI device or volume", node, major, minor);
-	errno = 0;
-	return -1;
-}
-
-int ubi_get_info(libubi_t desc, struct ubi_info *info)
-{
-	DIR *sysfs_ubi;
-	struct dirent *dirent;
-	struct libubi *lib = (struct libubi *)desc;
-
-	memset(info, '\0', sizeof(struct ubi_info));
-
-	if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) {
-		/*
-		 * Older UBI versions did not have control device, so we do not
-		 * panic here for compatibility reasons. May be few years later
-		 * we could return -1 here, but for now just set major:minor to
-		 * -1.
-		 */
-		info->ctrl_major = info->ctrl_minor = -1;
-	}
-
-	/*
-	 * We have to scan the UBI sysfs directory to identify how many UBI
-	 * devices are present.
-	 */
-	sysfs_ubi = opendir(lib->sysfs_ubi);
-	if (!sysfs_ubi)
-		return -1;
-
-	info->lowest_dev_num = INT_MAX;
-	while (1) {
-		int dev_num, ret;
-		char tmp_buf[256];
-
-		errno = 0;
-		dirent = readdir(sysfs_ubi);
-		if (!dirent)
-			break;
-
-		if (strlen(dirent->d_name) > 256) {
-			errmsg("invalid entry in %s: \"%s\"",
-			       lib->sysfs_ubi, dirent->d_name);
-			goto out_close;
-		}
-
-		ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s",
-			     &dev_num, tmp_buf);
-		if (ret == 1) {
-			info->dev_count += 1;
-			if (dev_num > info->highest_dev_num)
-				info->highest_dev_num = dev_num;
-			if (dev_num < info->lowest_dev_num)
-				info->lowest_dev_num = dev_num;
-		}
-	}
-
-	if (!dirent && errno) {
-		sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
-		goto out_close;
-	}
-
-	if (closedir(sysfs_ubi))
-		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
-
-	if (info->lowest_dev_num == INT_MAX)
-		info->lowest_dev_num = 0;
-
-	if (read_positive_int(lib->ubi_version, &info->version))
-		return -1;
-
-	return 0;
-
-out_close:
-	closedir(sysfs_ubi);
-	return -1;
-}
-
-int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
-{
-	int fd, ret;
-	struct ubi_mkvol_req r;
-	size_t n;
-
-	memset(&r, sizeof(struct ubi_mkvol_req), '\0');
-
-	desc = desc;
-	r.vol_id = req->vol_id;
-	r.alignment = req->alignment;
-	r.bytes = req->bytes;
-	r.vol_type = req->vol_type;
-
-	n = strlen(req->name);
-	if (n > UBI_MAX_VOLUME_NAME)
-		return -1;
-
-	strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
-	r.name_len = n;
-
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	ret = ioctl(fd, UBI_IOCMKVOL, &r);
-	if (ret == -1)
-		goto out_close;
-
-	req->vol_id = r.vol_id;
-
-#ifdef UDEV_SETTLE_HACK
-	if (system("udevsettle") == -1)
-		return -1;
-#endif
-
-out_close:
-	close(fd);
-	return ret;
-}
-
-int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
-{
-	int fd, ret;
-
-	desc = desc;
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
-	if (ret == -1)
-		goto out_close;
-
-#ifdef UDEV_SETTLE_HACK
-	if (system("udevsettle") == -1)
-		return -1;
-#endif
-
-out_close:
-	close(fd);
-	return ret;
-}
-
-int ubi_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol)
-{
-	int fd, ret;
-
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return -1;
-	ret = ioctl(fd, UBI_IOCRNVOL, rnvol);
-	if (ret == -1)
-		goto out_close;
-
-#ifdef UDEV_SETTLE_HACK
-	if (system("udevsettle") == -1)
-		return -1;
-#endif
-
-out_close:
-	close(fd);
-	return ret;
-}
-
-int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
-{
-	int fd, ret;
-	struct ubi_rsvol_req req;
-
-	desc = desc;
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	req.bytes = bytes;
-	req.vol_id = vol_id;
-
-	ret = ioctl(fd, UBI_IOCRSVOL, &req);
-	close(fd);
-	return ret;
-}
-
-int ubi_update_start(libubi_t desc, int fd, long long bytes)
-{
-	desc = desc;
-	if (ioctl(fd, UBI_IOCVOLUP, &bytes))
-		return -1;
-	return 0;
-}
-
-int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype)
-{
-	struct ubi_leb_change_req req;
-
-	desc = desc;
-	memset(&req, 0, sizeof(struct ubi_leb_change_req));
-	req.lnum = lnum;
-	req.bytes = bytes;
-	req.dtype = dtype;
-
-	if (ioctl(fd, UBI_IOCEBCH, &req))
-		return -1;
-	return 0;
-}
-
-int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
-{
-	DIR *sysfs_ubi;
-	struct dirent *dirent;
-	struct libubi *lib = (struct libubi *)desc;
-
-	memset(info, '\0', sizeof(struct ubi_dev_info));
-	info->dev_num = dev_num;
-
-	sysfs_ubi = opendir(lib->sysfs_ubi);
-	if (!sysfs_ubi)
-		return -1;
-
-	info->lowest_vol_id = INT_MAX;
-
-	while (1) {
-		int vol_id, ret, devno;
-		char tmp_buf[256];
-
-		errno = 0;
-		dirent = readdir(sysfs_ubi);
-		if (!dirent)
-			break;
-
-		if (strlen(dirent->d_name) > 256) {
-			errmsg("invalid entry in %s: \"%s\"",
-			       lib->sysfs_ubi, dirent->d_name);
-			goto out_close;
-		}
-
-		ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf);
-		if (ret == 2 && devno == dev_num) {
-			info->vol_count += 1;
-			if (vol_id > info->highest_vol_id)
-				info->highest_vol_id = vol_id;
-			if (vol_id < info->lowest_vol_id)
-				info->lowest_vol_id = vol_id;
-		}
-	}
-
-	if (!dirent && errno) {
-		sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
-		goto out_close;
-	}
-
-	if (closedir(sysfs_ubi))
-		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
-
-	if (info->lowest_vol_id == INT_MAX)
-		info->lowest_vol_id = 0;
-
-	if (dev_get_major(lib, dev_num, &info->major, &info->minor))
-		return -1;
-
-	if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs))
-		return -1;
-	if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs))
-		return -1;
-	if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
-		return -1;
-	if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size))
-		return -1;
-	if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
-		return -1;
-	if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
-		return -1;
-	if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
-		return -1;
-	if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
-		return -1;
-
-	info->avail_bytes = info->avail_lebs * info->leb_size;
-	info->total_bytes = info->total_lebs * info->leb_size;
-
-	return 0;
-
-out_close:
-	closedir(sysfs_ubi);
-	return -1;
-}
-
-int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
-{
-	int dev_num;
-	struct libubi *lib = (struct libubi *)desc;
-
-	if (dev_node2num(lib, node, &dev_num))
-		return -1;
-
-	return ubi_get_dev_info1(desc, dev_num, info);
-}
-
-int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
-		      struct ubi_vol_info *info)
-{
-	int ret;
-	struct libubi *lib = (struct libubi *)desc;
-	char buf[50];
-
-	memset(info, '\0', sizeof(struct ubi_vol_info));
-	info->dev_num = dev_num;
-	info->vol_id = vol_id;
-
-	if (dev_get_major(lib, dev_num, &info->dev_major, &info->dev_minor))
-		return -1;
-	if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor))
-		return -1;
-
-	ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50);
-	if (ret < 0)
-		return -1;
-
-	if (strncmp(buf, "static\n", ret) == 0)
-		info->type = UBI_STATIC_VOLUME;
-	else if (strncmp(buf, "dynamic\n", ret) == 0)
-		info->type = UBI_DYNAMIC_VOLUME;
-	else {
-		errmsg("bad value at \"%s\"", buf);
-		errno = EINVAL;
-		return -1;
-	}
-
-	ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
-			   &info->alignment);
-	if (ret)
-		return -1;
-	ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
-			  &info->data_bytes);
-	if (ret)
-		return -1;
-	ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs);
-	if (ret)
-		return -1;
-	ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size);
-	if (ret)
-		return -1;
-	ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
-			   &info->corrupted);
-	if (ret)
-		return -1;
-	info->rsvd_bytes = info->leb_size * info->rsvd_lebs;
-
-	ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
-			    UBI_VOL_NAME_MAX + 2);
-	if (ret < 0)
-		return -1;
-
-	info->name[ret - 1] = '\0';
-	return 0;
-}
-
-int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
-{
-	int vol_id, dev_num;
-	struct libubi *lib = (struct libubi *)desc;
-
-	if (vol_node2nums(lib, node, &dev_num, &vol_id))
-		return -1;
-
-	return ubi_get_vol_info1(desc, dev_num, vol_id, info);
-}
-
-int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name,
-			 struct ubi_vol_info *info)
-{
-	int i, err;
-	unsigned int nlen = strlen(name);
-	struct ubi_dev_info dev_info;
-
-	if (nlen == 0) {
-		errmsg("bad \"name\" input parameter");
-		errno = EINVAL;
-		return -1;
-	}
-
-	err = ubi_get_dev_info1(desc, dev_num, &dev_info);
-	if (err)
-		return err;
-
-	for (i = dev_info.lowest_vol_id;
-	     i <= dev_info.highest_vol_id; i++) {
-		err = ubi_get_vol_info1(desc, dev_num, i, info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (nlen == strlen(info->name) && !strcmp(name, info->name))
-			return 0;
-	}
-
-	errno = ENOENT;
-	return -1;
-}
diff --git a/ubi-utils/new-utils/src/libubi_int.h b/ubi-utils/new-utils/src/libubi_int.h
deleted file mode 100644
index 2e664b8..0000000
--- a/ubi-utils/new-utils/src/libubi_int.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Artem Bityutskiy
- *
- * UBI (Unsorted Block Images) library.
- */
-
-#ifndef __LIBUBI_INT_H__
-#define __LIBUBI_INT_H__
-
-#include <string.h>
-#include <errno.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * 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 DEV_DEV           "dev"
-#define DEV_AVAIL_EBS     "avail_eraseblocks"
-#define DEV_TOTAL_EBS     "total_eraseblocks"
-#define DEV_BAD_COUNT     "bad_peb_count"
-#define DEV_EB_SIZE       "eraseblock_size"
-#define DEV_MAX_EC        "max_ec"
-#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"
-#define VOL_DATA_BYTES    "data_bytes"
-#define VOL_RSVD_EBS      "reserved_ebs"
-#define VOL_EB_SIZE       "usable_eb_size"
-#define VOL_CORRUPTED     "corrupted"
-#define VOL_NAME          "name"
-
-/**
- * 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
- */
-struct libubi
-{
-	char *sysfs;
-	char *sysfs_ctrl;
-	char *ctrl_dev;
-	char *sysfs_ubi;
-	char *ubi_dev;
-	char *ubi_version;
-	char *dev_dev;
-	char *dev_avail_ebs;
-	char *dev_total_ebs;
-	char *dev_bad_count;
-	char *dev_eb_size;
-	char *dev_max_ec;
-	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;
-	char *vol_alignment;
-	char *vol_data_bytes;
-	char *vol_rsvd_ebs;
-	char *vol_eb_size;
-	char *vol_corrupted;
-	char *vol_name;
-	char *vol_max_count;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__LIBUBI_INT_H__ */
diff --git a/ubi-utils/new-utils/src/libubigen.c b/ubi-utils/new-utils/src/libubigen.c
deleted file mode 100644
index 91bb274..0000000
--- a/ubi-utils/new-utils/src/libubigen.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- * Copyright (C) 2008 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Generating UBI images.
- *
- * Authors: Oliver Lohmann
- *          Artem Bityutskiy
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <mtd/ubi-media.h>
-#include <mtd_swab.h>
-#include <libubigen.h>
-#include "crc32.h"
-#include "common.h"
-
-#define PROGRAM_NAME "libubigen"
-
-/**
- * ubigen_info_init - initialize libubigen.
- * @ui: libubigen information
- * @peb_size: flash physical eraseblock size
- * @min_io_size: flash minimum input/output unit size
- * @subpage_size: flash sub-page, if present (has to be equivalent to
- *                @min_io_size if does not exist)
- * @vid_hdr_offs: offset of the VID header
- * @ubi_ver: UBI version
- */
-void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
-		      int subpage_size, int vid_hdr_offs, int ubi_ver)
-{
-	if (!vid_hdr_offs) {
-		vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1;
-		vid_hdr_offs /= subpage_size;
-		vid_hdr_offs *= subpage_size;
-	}
-
-	ui->peb_size = peb_size;
-	ui->min_io_size = min_io_size;
-	ui->vid_hdr_offs = vid_hdr_offs;
-	ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1;
-	ui->data_offs /= min_io_size;
-	ui->data_offs *= min_io_size;
-	ui->leb_size = peb_size - ui->data_offs;
-	ui->ubi_ver = ubi_ver;
-
-	ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE;
-	if (ui->max_volumes > UBI_MAX_VOLUMES)
-		ui->max_volumes = UBI_MAX_VOLUMES;
-	ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE;
-}
-
-/**
- * ubigen_create_empty_vtbl - creates empty volume table.
- *
- * This function creates an empty volume table and returns a pointer to it in
- * case of success and %NULL in case of failure. The returned object has to be
- * freed with 'free()' call.
- */
-struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui)
-{
-	struct ubi_vtbl_record *vtbl;
-	int i;
-
-	vtbl = calloc(1, ui->vtbl_size);
-	if (!vtbl) {
-		sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
-		return NULL;
-	}
-
-	for (i = 0; i < ui->max_volumes; i++) {
-		uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i],
-				     UBI_VTBL_RECORD_SIZE_CRC);
-		vtbl[i].crc = cpu_to_be32(crc);
-	}
-
-	return vtbl;
-}
-
-/**
- * ubigen_add_volume - add a volume to the volume table.
- * @ui: libubigen information
- * @vi: volume information
- * @vtbl: volume table to add to
- *
- * This function adds volume described by input parameters to the volume table
- * @vtbl.
- */
-int ubigen_add_volume(const struct ubigen_info *ui,
-		      const struct ubigen_vol_info *vi,
-		      struct ubi_vtbl_record *vtbl)
-{
-	struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
-	uint32_t tmp;
-
-	if (vi->id >= ui->max_volumes)
-		return errmsg("too high volume id %d, max. volumes is %d",
-			      vi->id, ui->max_volumes);
-
-	if (vi->alignment >= ui->leb_size)
-		return errmsg("too large alignment %d, max is %d (LEB size)",
-			      vi->alignment, ui->leb_size);
-
-	memset(vtbl_rec, '\0', sizeof(struct ubi_vtbl_record));
-	tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size;
-	vtbl_rec->reserved_pebs = cpu_to_be32(tmp);
-	vtbl_rec->alignment = cpu_to_be32(vi->alignment);
-	vtbl_rec->vol_type = vi->type;
-	tmp = ui->leb_size % vi->alignment;
-	vtbl_rec->data_pad = cpu_to_be32(tmp);
-	vtbl_rec->flags = vi->flags;
-
-	memcpy(vtbl_rec->name, vi->name, vi->name_len);
-	vtbl_rec->name[vi->name_len] = '\0';
-	vtbl_rec->name_len = cpu_to_be16(vi->name_len);
-
-	tmp = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
-	vtbl_rec->crc =	 cpu_to_be32(tmp);
-	return 0;
-}
-
-/**
- * ubigen_init_ec_hdr - initialize EC header.
- * @ui: libubigen information
- * @hdr: the EC header to initialize
- * @ec: erase counter value
- */
-void ubigen_init_ec_hdr(const struct ubigen_info *ui,
-		        struct ubi_ec_hdr *hdr, long long ec)
-{
-	uint32_t crc;
-
-	memset(hdr, '\0', sizeof(struct ubi_ec_hdr));
-
-	hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
-	hdr->version = ui->ubi_ver;
-	hdr->ec = cpu_to_be64(ec);
-	hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs);
-
-	hdr->data_offset = cpu_to_be32(ui->data_offs);
-
-	crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
-	hdr->hdr_crc = cpu_to_be32(crc);
-}
-
-/**
- * init_vid_hdr - initialize VID header.
- * @ui: libubigen information
- * @vi: volume information
- * @hdr: the VID header to initialize
- * @lnum: logical eraseblock number
- * @data: the contents of the LEB (static volumes only)
- * @data_size: amount of data in this LEB (static volumes only)
- *
- * Note, @used_ebs, @data and @data_size are ignored in case of dynamic
- * volumes.
- */
-static void init_vid_hdr(const struct ubigen_info *ui,
-			 const struct ubigen_vol_info *vi,
-			 struct ubi_vid_hdr *hdr, int lnum,
-			 const void *data, int data_size)
-{
-	uint32_t crc;
-
-	memset(hdr, '\0', sizeof(struct ubi_vid_hdr));
-
-	hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
-	hdr->version = ui->ubi_ver;
-	hdr->vol_type = vi->type;
-	hdr->vol_id = cpu_to_be32(vi->id);
-	hdr->lnum = cpu_to_be32(lnum);
-	hdr->data_pad = cpu_to_be32(vi->data_pad);
-	hdr->compat = vi->compat;
-
-	if (vi->type == UBI_VID_STATIC) {
-		hdr->data_size = cpu_to_be32(data_size);
-		hdr->used_ebs = cpu_to_be32(vi->used_ebs);
-		crc = crc32(UBI_CRC32_INIT, data, data_size);
-		hdr->data_crc = cpu_to_be32(crc);
-	}
-
-	crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
-	hdr->hdr_crc = cpu_to_be32(crc);
-}
-
-/**
- * ubigen_write_volume - write UBI volume.
- * @ui: libubigen information
- * @vi: volume information
- * @ec: erase coutner value to put to EC headers
- * @bytes: volume size in bytes
- * @in: input file descriptor (has to be properly seeked)
- * @out: output file descriptor
- *
- * This function reads the contents of the volume from the input file @in and
- * writes the UBI volume to the output file @out. Returns zero on success and
- * %-1 on failure.
- */
-int ubigen_write_volume(const struct ubigen_info *ui,
-			const struct ubigen_vol_info *vi, long long ec,
-			long long bytes, int in, int out)
-{
-	int len = vi->usable_leb_size, rd, lnum = 0;
-	char inbuf[ui->leb_size], outbuf[ui->peb_size];
-
-	if (vi->id >= ui->max_volumes)
-		return errmsg("too high volume id %d, max. volumes is %d",
-			      vi->id, ui->max_volumes);
-
-	if (vi->alignment >= ui->leb_size)
-		return errmsg("too large alignment %d, max is %d (LEB size)",
-			      vi->alignment, ui->leb_size);
-
-	memset(outbuf, 0xFF, ui->data_offs);
-	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec);
-
-	while (bytes) {
-		int l;
-		struct ubi_vid_hdr *vid_hdr;
-
-		if (bytes < len)
-			len = bytes;
-		bytes -= len;
-
-		l = len;
-		do {
-			rd = read(in, inbuf + len - l, l);
-			if (rd != l)
-				return sys_errmsg("cannot read %d bytes from the input file", l);
-
-			l -= rd;
-		} while (l);
-
-		vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
-		init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
-
-		memcpy(outbuf + ui->data_offs, inbuf, len);
-		memset(outbuf + ui->data_offs + len, 0xFF,
-		       ui->peb_size - ui->data_offs - len);
-
-		if (write(out, outbuf, ui->peb_size) != ui->peb_size)
-			return sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
-
-		lnum += 1;
-	}
-
-	return 0;
-}
-
-/**
- * ubigen_write_layout_vol - write UBI layout volume
- * @ui: libubigen information
- * @peb1: physical eraseblock number to write the first volume table copy
- * @peb2: physical eraseblock number to write the second volume table copy
- * @ec1: erase counter value for @peb1
- * @ec2: erase counter value for @peb1
- * @vtbl: volume table
- * @fd: output file descriptor seeked to the proper position
- *
- * This function creates the UBI layout volume which contains 2 copies of the
- * volume table. Returns zero in case of success and %-1 in case of failure.
- */
-int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
-			    long long ec1, long long ec2,
-			    struct ubi_vtbl_record *vtbl, int fd)
-{
-	int ret;
-	struct ubigen_vol_info vi;
-	char outbuf[ui->peb_size];
-	struct ubi_vid_hdr *vid_hdr;
-	off_t seek;
-
-	vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
-	vi.id = UBI_LAYOUT_VOLUME_ID;
-	vi.alignment = UBI_LAYOUT_VOLUME_ALIGN;
-	vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
-	vi.usable_leb_size = ui->leb_size - vi.data_pad;
-	vi.data_pad = ui->leb_size - vi.usable_leb_size;
-	vi.type = UBI_LAYOUT_VOLUME_TYPE;
-	vi.name = UBI_LAYOUT_VOLUME_NAME;
-	vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
-	vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
-
-	memset(outbuf, 0xFF, ui->data_offs);
-	vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
-	memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size);
-	memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF,
-	       ui->peb_size - ui->data_offs - ui->vtbl_size);
-
-	seek = peb1 * ui->peb_size;
-	if (lseek(fd, seek, SEEK_SET) != seek)
-		return sys_errmsg("cannot seek output file");
-	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1);
-	init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
-	ret = write(fd, outbuf, ui->peb_size);
-	if (ret != ui->peb_size)
-		return sys_errmsg("cannot write %d bytes", ui->peb_size);
-
-	seek = peb2 * ui->peb_size;
-	if (lseek(fd, seek, SEEK_SET) != seek)
-		return sys_errmsg("cannot seek output file");
-	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2);
-	init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
-	ret = write(fd, outbuf, ui->peb_size);
-	if (ret != ui->peb_size)
-		return sys_errmsg("cannot write %d bytes", ui->peb_size);
-
-	return 0;
-}
diff --git a/ubi-utils/new-utils/src/ubiattach.c b/ubi-utils/new-utils/src/ubiattach.c
deleted file mode 100644
index 1f72620..0000000
--- a/ubi-utils/new-utils/src/ubiattach.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2007 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * An utility to attach MTD devices to UBI.
- *
- * Author: Artem Bityutskiy
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libubi.h>
-#include "common.h"
-
-#define PROGRAM_VERSION "1.0"
-#define PROGRAM_NAME    "ubiattach"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int devn;
-	int mtdn;
-	int vidoffs;
-	const char *node;
-};
-
-static struct args args = {
-	.devn = UBI_DEV_NUM_AUTO,
-	.mtdn = -1,
-	.vidoffs = 0,
-	.node = NULL,
-};
-
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
-			 " - a tool to attach MTD device to UBI.";
-
-static const char *optionsstr =
-"-d, --devn=<UBI device number>  the number to assign to the newly created UBI device\n"
-"                                (the number is assigned automatically if this is not\n"
-"                                specified\n"
-"-m, --mtdn=<MTD device number>  MTD device number to attach\n"
-"-O, --vid-hdr-offset            VID header offset (do not specify this unless you\n"
-"                                really know what you do and the optimal defaults will\n"
-"                                be used)\n"
-"-h, --help                      print help message\n"
-"-V, --version                   print program version";
-
-static const char *usage =
-"Usage: " PROGRAM_NAME " <UBI control device node file name> [-m <MTD device number>] [-d <UBI device number>]\n"
-"\t\t[--mtdn=<MTD device number>] [--devn <UBI device number>]\n"
-"Example 1: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 - attach MTD device 0 (mtd0) to UBI\n"
-"Example 2: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 -d 3 - attach MTD device 0 (mtd0) to UBI and\n"
-"           and create UBI device number 3 (ubi3)";
-
-static const struct option long_options[] = {
-	{ .name = "devn",           .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ .name = "mtdn",           .has_arg = 1, .flag = NULL, .val = 'm' },
-	{ .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
-	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key;
-		char *endp;
-
-		key = getopt_long(argc, argv, "m:d:O:hV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'd':
-			args.devn = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.devn < 0)
-				return errmsg("bad UBI device number: \"%s\"", optarg);
-
-			break;
-
-		case 'm':
-			args.mtdn = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.mtdn < 0)
-				return errmsg("bad MTD device number: \"%s\"", optarg);
-
-			break;
-
-		case 'O':
-			args.vidoffs = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.vidoffs <= 0)
-				return errmsg("bad VID header offset: \"%s\"", optarg);
-
-			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 ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc)
-		return errmsg("UBI control device name was not specified (use -h for help)");
-	else if (optind != argc - 1)
-		return errmsg("more then one UBI control device specified (use -h for help)");
-
-	if (args.mtdn == -1)
-		return errmsg("MTD device number was not specified (use -h for help)");
-
-	args.node = argv[optind];
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-	struct ubi_info ubi_info;
-	struct ubi_dev_info dev_info;
-	struct ubi_attach_request req;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	libubi = libubi_open(1);
-	if (libubi == NULL)
-		return sys_errmsg("cannot open libubi");
-
-	/*
-	 * Make sure the kernel is fresh enough and this feature is supported.
-	 */
-	err = ubi_get_info(libubi, &ubi_info);
-	if (err) {
-		sys_errmsg("cannot get UBI information");
-		goto out_libubi;
-	}
-
-	if (ubi_info.ctrl_major == -1) {
-		errmsg("MTD attach/detach feature is not supported by your kernel");
-		goto out_libubi;
-	}
-
-	req.dev_num = args.devn;
-	req.mtd_num = args.mtdn;
-	req.vid_hdr_offset = args.vidoffs;
-
-	err = ubi_attach_mtd(libubi, args.node, &req);
-	if (err) {
-		sys_errmsg("cannot attach mtd%d", args.mtdn);
-		goto out_libubi;
-	}
-
-	/* Print some information about the new UBI device */
-	err = ubi_get_dev_info1(libubi, req.dev_num, &dev_info);
-	if (err) {
-		sys_errmsg("cannot get information about newly created UBI device");
-		goto out_libubi;
-	}
-
-	printf("UBI device number %d, total %d LEBs (", dev_info.dev_num, dev_info.total_lebs);
-	ubiutils_print_bytes(dev_info.total_bytes, 0);
-	printf("), available %d LEBs (", dev_info.avail_lebs);
-	ubiutils_print_bytes(dev_info.avail_bytes, 0);
-	printf("), LEB size ");
-	ubiutils_print_bytes(dev_info.leb_size, 1);
-	printf("\n");
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/new-utils/src/ubicrc32.c b/ubi-utils/new-utils/src/ubicrc32.c
deleted file mode 100644
index d39af10..0000000
--- a/ubi-utils/new-utils/src/ubicrc32.c
+++ /dev/null
@@ -1,124 +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.
- */
-
-/*
- * 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 <unistd.h>
-#include <mtd/ubi-media.h>
-
-#include "crc32.h"
-#include "common.h"
-
-#define BUFSIZE 4096
-
-#define PROGRAM_VERSION "1.0"
-#define PROGRAM_NAME    "ubicrc32"
-
-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/new-utils/src/ubidetach.c b/ubi-utils/new-utils/src/ubidetach.c
deleted file mode 100644
index 50670d0..0000000
--- a/ubi-utils/new-utils/src/ubidetach.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2007 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * An utility to delete UBI devices (detach MTD devices from UBI).
- *
- * Author: Artem Bityutskiy
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libubi.h>
-#include "common.h"
-
-#define PROGRAM_VERSION "1.0"
-#define PROGRAM_NAME    "ubidetach"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int devn;
-	int mtdn;
-	const char *node;
-};
-
-static struct args args = {
-	.devn = UBI_DEV_NUM_AUTO,
-	.mtdn = -1,
-	.node = NULL,
-};
-
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
-" - a tool to remove UBI devices (detach MTD devices from UBI)";
-
-static const char *optionsstr =
-"-d, --devn=<UBI device number>  UBI device number to delete\n"
-"-m, --mtdn=<MTD device number>  or altrnatively, MTD device number to detach -\n"
-"                                this will delete corresponding UBI device\n"
-"-h, --help                      print help message\n"
-"-V, --version                   print program version";
-
-static const char *usage =
-"Usage: " PROGRAM_NAME "<UBI control device node file name> [-d <UBI device number>] [-m <MTD device number>]\n"
-"\t\t[--devn <UBI device number>] [--mtdn=<MTD device number>]\n"
-"Example 1: " PROGRAM_NAME " /dev/ubi_ctrl -d 2 - delete UBI device 2 (ubi2)\n"
-"Example 2: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 - detach MTD device 0 (mtd0)";
-
-static const struct option long_options[] = {
-	{ .name = "devn",    .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ .name = "mtdn",    .has_arg = 1, .flag = NULL, .val = 'm' },
-	{ .name = "help",    .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key;
-		char *endp;
-
-		key = getopt_long(argc, argv, "m:d:hV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'd':
-			args.devn = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.devn < 0)
-				return errmsg("bad UBI device number: \"%s\"", optarg);
-
-			break;
-
-		case 'm':
-			args.mtdn = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.mtdn < 0)
-				return errmsg("bad MTD device number: \"%s\"", optarg);
-
-			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 ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc)
-		return errmsg("UBI control device name was not specified (use -h for help)");
-	else if (optind != argc - 1)
-		return errmsg("more then one UBI control device specified (use -h for help)");
-
-	if (args.mtdn == -1 && args.devn == -1)
-		return errmsg("neither MTD nor UBI devices were specified (use -h for help)");
-
-	if (args.mtdn != -1 && args.devn != -1)
-		return errmsg("specify either MTD or UBI device (use -h for help)");
-
-	args.node = argv[optind];
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-	struct ubi_info ubi_info;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	libubi = libubi_open(1);
-	if (libubi == NULL)
-		return sys_errmsg("cannot open libubi");
-
-	/*
-	 * Make sure the kernel is fresh enough and this feature is supported.
-	 */
-	err = ubi_get_info(libubi, &ubi_info);
-	if (err) {
-		sys_errmsg("cannot get UBI information");
-		goto out_libubi;
-	}
-
-	if (ubi_info.ctrl_major == -1) {
-		errmsg("MTD detach/detach feature is not supported by your kernel");
-		goto out_libubi;
-	}
-
-	if (args.devn != -1) {
-		err = ubi_remove_dev(libubi, args.node, args.devn);
-		if (err) {
-			sys_errmsg("cannot remove ubi%d", args.devn);
-			goto out_libubi;
-		}
-	} else {
-		err = ubi_detach_mtd(libubi, args.node, args.mtdn);
-		if (err) {
-			sys_errmsg("cannot detach mtd%d", args.mtdn);
-			goto out_libubi;
-		}
-	}
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
-
diff --git a/ubi-utils/new-utils/src/ubiformat.c b/ubi-utils/new-utils/src/ubiformat.c
deleted file mode 100644
index 0074c7a..0000000
--- a/ubi-utils/new-utils/src/ubiformat.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * An utility to format MTD devices into UBI and flash UBI images.
- *
- * Author: Artem Bityutskiy
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <fcntl.h>
-
-#include <libubi.h>
-#include <libmtd.h>
-#include <libscan.h>
-#include <libubigen.h>
-#include <mtd_swab.h>
-#include "crc32.h"
-#include "common.h"
-
-#define PROGRAM_VERSION "1.0"
-#define PROGRAM_NAME    "ubiformat"
-
-/* The variables below are set by command line arguments */
-struct args {
-	unsigned int yes:1;
-	unsigned int quiet:1;
-	unsigned int verbose:1;
-	unsigned int override_ec:1;
-	unsigned int novtbl:1;
-	int subpage_size;
-	int vid_hdr_offs;
-	int ubi_ver;
-	off_t image_sz;
-	long long ec;
-	const char *image;
-	const char *node;
-};
-
-static struct args args =
-{
-	.ubi_ver = 1,
-};
-
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
-		" - a tool to format MTD devices and flash UBI images";
-
-static const char *optionsstr =
-"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
-"                             headers, e.g. sub-page size in case of NAND\n"
-"                             flash (equivalent to the minimum input/output\n"
-"                             unit size by default)\n"
-"-O, --vid-hdr-offset=<offs>  offset if the VID header from start of the\n"
-"                             physical eraseblock (default is the next\n"
-"                             minimum I/O unit or sub-page after the EC\n"
-"                             header)\n"
-"-n, --no-volume-table        only erase all eraseblock and preserve erase\n"
-"                             counters, do not write empty volume table\n"
-"-f, --flash-image=<file>     flash image file, or '-' for stdin\n"
-"-S, --image-size=<bytes>     bytes in input, if not reading from file\n"
-"-e, --erase-counter=<value>  use <value> as the erase counter value for all\n"
-"                             eraseblocks\n"
-"-y, --yes                    assume the answer is \"yes\" for all question\n"
-"                             this program would otherwise ask\n"
-"-q, --quiet                  suppress progress percentage information\n"
-"-v, --verbose                be verbose\n"
-"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
-"                             (default is 1)\n"
-"-h, -?, --help               print help message\n"
-"-V, --version                print program version\n";
-
-static const char *usage =
-"Usage: " PROGRAM_NAME " <MTD device node file name> [-h] [-V] [-y] [-q] [-v]\n"
-"\t\t\t[-x <num>] [-E <value>] [-s <bytes>] [-O <offs>] [-n]\n"
-"\t\t\t[--help] [--version] [--yes] [--verbose] [--quiet]\n"
-"\t\t\t[--ec=<value>] [--vid-hdr-offset=<offs>]\n"
-"\t\t\t[--ubi-ver=<num>] [--no-volume-table]\n"
-"\t\t\t[--flash-image=<file>] [--image-size=<bytes>]\n\n"
-
-"Example 1: " PROGRAM_NAME " /dev/mtd0 -y - format MTD device number 0 and do\n"
-"           not ask questions.\n"
-"Example 2: " PROGRAM_NAME " /dev/mtd0 -q -e 0 - format MTD device number 0,\n"
-"           be quiet and force erase counter value 0.";
-
-static const struct option long_options[] = {
-	{ .name = "sub-page-size",   .has_arg = 1, .flag = NULL, .val = 's' },
-	{ .name = "vid-hdr-offset",  .has_arg = 1, .flag = NULL, .val = 'O' },
-	{ .name = "no-volume-table", .has_arg = 0, .flag = NULL, .val = 'n' },
-	{ .name = "flash-image",     .has_arg = 1, .flag = NULL, .val = 'f' },
-	{ .name = "image-size",      .has_arg = 1, .flag = NULL, .val = 'S' },
-	{ .name = "yes",             .has_arg = 0, .flag = NULL, .val = 'y' },
-	{ .name = "erase-counter",   .has_arg = 1, .flag = NULL, .val = 'e' },
-	{ .name = "quiet",           .has_arg = 0, .flag = NULL, .val = 'q' },
-	{ .name = "verbose",         .has_arg = 0, .flag = NULL, .val = 'v' },
-	{ .name = "ubi-ver",         .has_arg = 1, .flag = NULL, .val = 'x' },
-	{ .name = "help",            .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",         .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key;
-		char *endp;
-
-		key = getopt_long(argc, argv, "nh?Vyqve:x:s:O:f:S:", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 's':
-			args.subpage_size = ubiutils_get_bytes(optarg);
-			if (args.subpage_size <= 0)
-				return errmsg("bad sub-page size: \"%s\"", optarg);
-			if (!is_power_of_2(args.subpage_size))
-				return errmsg("sub-page size should be power of 2");
-			break;
-
-		case 'O':
-			args.vid_hdr_offs = strtoul(optarg, &endp, 0);
-			if (args.vid_hdr_offs <= 0 || *endp != '\0' || endp == optarg)
-				return errmsg("bad VID header offset: \"%s\"", optarg);
-			break;
-
-		case 'e':
-			args.ec = strtoull(optarg, &endp, 0);
-			if (args.ec <= 0 || *endp != '\0' || endp == optarg)
-				return errmsg("bad erase counter value: \"%s\"", optarg);
-			if (args.ec >= EC_MAX)
-				return errmsg("too high erase %llu, counter, max is %u", args.ec, EC_MAX);
-			args.override_ec = 1;
-			break;
-
-		case 'f':
-			args.image = optarg;
-			break;
-
-		case 'S':
-			args.image_sz = ubiutils_get_bytes(optarg);
-			if (args.image_sz <= 0)
-				return errmsg("bad image-size: \"%s\"", optarg);
-			break;
-
-		case 'n':
-			args.novtbl = 1;
-			break;
-
-		case 'y':
-			args.yes = 1;
-			break;
-
-		case 'q':
-			args.quiet = 1;
-			break;
-
-		case 'x':
-			args.ubi_ver = strtoul(optarg, &endp, 0);
-			if (args.ubi_ver < 0 || *endp != '\0' || endp == optarg)
-				return errmsg("bad UBI version: \"%s\"", optarg);
-			break;
-
-		case 'v':
-			args.verbose = 1;
-			break;
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case 'h':
-		case '?':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (args.quiet && args.verbose)
-		return errmsg("using \"-q\" and \"-v\" at the same time does not make sense");
-
-	if (optind == argc)
-		return errmsg("MTD device name was not specified (use -h for help)");
-	else if (optind != argc - 1)
-		return errmsg("more then one MTD device specified (use -h for help)");
-
-	if (args.image && args.novtbl)
-		return errmsg("-n cannot be used together with -f");
-
-	args.node = argv[optind];
-	return 0;
-}
-
-static int want_exit(void)
-{
-	char buf[4];
-
-	while (1) {
-		normsg_cont("continue? (yes/no)  ");
-		if (scanf("%3s", buf) == EOF) {
-			sys_errmsg("scanf returned unexpected EOF, assume \"yes\"");
-			return 1;
-		}
-		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))
-			return 0;
-		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))
-			return 1;
-	}
-}
-
-static int answer_is_yes(void)
-{
-	char buf[4];
-
-	while (1) {
-		if (scanf("%3s", buf) == EOF) {
-			sys_errmsg("scanf returned unexpected EOF, assume \"no\"");
-			return 0;
-		}
-		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))
-			return 1;
-		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))
-			return 0;
-	}
-}
-
-static void print_bad_eraseblocks(const struct mtd_info *mtd,
-				  const struct ubi_scan_info *si)
-{
-	int first = 1, eb;
-
-	if (si->bad_cnt == 0)
-		return;
-
-	normsg_cont("bad eraseblocks: ");
-	for (eb = 0; eb < mtd->eb_cnt; eb++) {
-		if (si->ec[eb] != EB_BAD)
-			continue;
-		if (first) {
-			printf("%d", eb);
-			first = 0;
-		} else
-			printf(", %d", eb);
-	}
-	printf("\n");
-}
-
-static int change_ec(struct ubi_ec_hdr *hdr, long long ec)
-{
-	uint32_t crc;
-
-	/* Check the EC header */
-	if (be32_to_cpu(hdr->magic) != UBI_EC_HDR_MAGIC)
-		return errmsg("bad UBI magic %#08x, should be %#08x",
-			      be32_to_cpu(hdr->magic), UBI_EC_HDR_MAGIC);
-
-	crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
-	if (be32_to_cpu(hdr->hdr_crc) != crc)
-		return errmsg("bad CRC %#08x, should be %#08x\n",
-			      crc, be32_to_cpu(hdr->hdr_crc));
-
-	hdr->ec = cpu_to_be64(ec);
-	crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
-	hdr->hdr_crc = cpu_to_be32(crc);
-
-	return 0;
-}
-
-static int drop_ffs(const struct mtd_info *mtd, const void *buf, int len)
-{
-	int i;
-
-        for (i = len - 1; i >= 0; i--)
-		if (((const uint8_t *)buf)[i] != 0xFF)
-		      break;
-
-        /* The resulting length must be aligned to the minimum flash I/O size */
-        len = i + 1;
-	len = (len + mtd->min_io_size - 1) / mtd->min_io_size;
-	len *=  mtd->min_io_size;
-        return len;
-}
-
-static int open_file(off_t *sz)
-{
-	int fd;
-
-	if (!strcmp(args.image, "-")) {
-		if (args.image_sz == 0)
-			return errmsg("must use '-S' with non-zero value when reading from stdin");
-
-		*sz = args.image_sz;
-		fd  = dup(STDIN_FILENO);
-		if (fd < 0)
-			return sys_errmsg("failed to dup stdin");
-	} else {
-		struct stat st;
-
-		if (stat(args.image, &st))
-			return sys_errmsg("cannot open \"%s\"", args.image);
-
-		*sz = st.st_size;
-		fd  = open(args.image, O_RDONLY);
-		if (fd == -1)
-			return sys_errmsg("cannot open \"%s\"", args.image);
-	}
-
-	return fd;
-}
-
-static int read_all(int fd, void *buf, size_t len)
-{
-	while (len > 0) {
-		ssize_t l = read(fd, buf, len);
-		if (l == 0)
-			return errmsg("eof reached; %zu bytes remaining", len);
-		else if (l > 0) {
-			buf += l;
-			len -= l;
-		} else if (errno == EINTR || errno == EAGAIN)
-			continue;
-		else
-			return sys_errmsg("reading failed; %zu bytes remaining", len);
-	}
-
-	return 0;
-}
-
-static int flash_image(const struct mtd_info *mtd, struct ubi_scan_info *si)
-{
-	int fd, img_ebs, eb, written_ebs = 0, divisor;
-	off_t st_size;
-
-	fd = open_file(&st_size);
-	if (fd < 0)
-		return fd;
-
-	img_ebs = st_size / mtd->eb_size;
-
-	if (img_ebs > si->good_cnt) {
-		sys_errmsg("file \"%s\" is too large (%lld bytes)",
-			   args.image, (long long)st_size);
-		goto out_close;
-	}
-
-	if (st_size % mtd->eb_size) {
-		return sys_errmsg("file \"%s\" (size %lld bytes) is not multiple of eraseblock size (%d bytes)",
-				  args.image, (long long)st_size, mtd->eb_size);
-		goto out_close;
-	}
-
-	verbose(args.verbose, "will write %d eraseblocks", img_ebs);
-	divisor = img_ebs;
-	for (eb = 0; eb < mtd->eb_cnt; eb++) {
-		int err, new_len;
-		char buf[mtd->eb_size];
-		long long ec;
-
-		if (!args.quiet && !args.verbose) {
-			printf("\r" PROGRAM_NAME ": flashing eraseblock %d -- %2lld %% complete  ",
-			       eb, (long long)(eb + 1) * 100 / divisor);
-			fflush(stdout);
-		}
-
-		if (si->ec[eb] == EB_BAD) {
-			divisor += 1;
-			continue;
-		}
-
-		if (args.verbose) {
-			normsg_cont("eraseblock %d: erase", eb);
-			fflush(stdout);
-		}
-
-		err = mtd_erase(mtd, eb);
-		if (err) {
-			sys_errmsg("failed to erase eraseblock %d", eb);
-			goto out_close;
-		}
-
-		err = read_all(fd, buf, mtd->eb_size);
-		if (err) {
-			sys_errmsg("failed to read eraseblock %d from \"%s\"",
-				   written_ebs, args.image);
-			goto out_close;
-		}
-
-
-		if (si->ec[eb] <= EC_MAX)
-			ec = si->ec[eb] + 1;
-		else if (!args.override_ec)
-			ec = si->mean_ec;
-		else
-			ec = args.ec;
-
-		if (args.verbose) {
-			printf(", change EC to %lld", ec);
-			fflush(stdout);
-		}
-
-		err = change_ec((struct ubi_ec_hdr *)buf, ec);
-		if (err) {
-			errmsg("bad EC header at eraseblock %d of \"%s\"",
-			       written_ebs, args.image);
-			goto out_close;
-		}
-
-		if (args.verbose) {
-			printf(", write data\n");
-			fflush(stdout);
-		}
-
-		new_len = drop_ffs(mtd, buf, mtd->eb_size);
-
-		err = mtd_write(mtd, eb, 0, buf, new_len);
-		if (err) {
-			sys_errmsg("cannot write eraseblock %d", eb);
-			goto out_close;
-		}
-		if (++written_ebs >= img_ebs)
-			break;
-	}
-
-	if (!args.quiet && !args.verbose)
-		printf("\n");
-	close(fd);
-	return eb + 1;
-
-out_close:
-	close(fd);
-	return -1;
-}
-
-static int format(const struct mtd_info *mtd, const struct ubigen_info *ui,
-		  const struct ubi_scan_info *si, int start_eb, int novtbl)
-{
-	int eb, err, write_size;
-	struct ubi_ec_hdr *hdr;
-	struct ubi_vtbl_record *vtbl;
-	int eb1 = -1, eb2 = -1;
-	long long ec1 = -1, ec2 = -1;
-
-	write_size = UBI_EC_HDR_SIZE + mtd->subpage_size - 1;
-	write_size /= mtd->subpage_size;
-	write_size *= mtd->subpage_size;
-	hdr = malloc(write_size);
-	if (!hdr)
-		return sys_errmsg("cannot allocate %d bytes of memory", write_size);
-
-	memset(hdr, 0xFF, write_size);
-
-	for (eb = start_eb; eb < mtd->eb_cnt; eb++) {
-		long long ec;
-
-		if (!args.quiet && !args.verbose) {
-			printf("\r" PROGRAM_NAME ": formatting eraseblock %d -- %2lld %% complete  ",
-			       eb, (long long)(eb + 1 - start_eb) * 100 / (mtd->eb_cnt - start_eb));
-			fflush(stdout);
-		}
-
-		if (si->ec[eb] == EB_BAD)
-			continue;
-
-		if (si->ec[eb] <= EC_MAX)
-			ec = si->ec[eb] + 1;
-		else if (!args.override_ec)
-			ec = si->mean_ec;
-		else
-			ec = args.ec;
-		ubigen_init_ec_hdr(ui, hdr, ec);
-
-		if (args.verbose) {
-			normsg_cont("eraseblock %d: erase", eb);
-			fflush(stdout);
-		}
-
-		err = mtd_erase(mtd, eb);
-		if (err) {
-			if (!args.quiet)
-				printf("\n");
-			sys_errmsg("failed to erase eraseblock %d", eb);
-			goto out_free;
-		}
-
-		if ((eb1 == -1 || eb2 == -1) && !novtbl) {
-			if (eb1 == -1) {
-				eb1 = eb;
-				ec1 = ec;
-			} else if (eb2 == -1) {
-				eb2 = eb;
-				ec2 = ec;
-			}
-			if (args.verbose)
-				printf(", do not write EC, leave for vtbl\n");
-			continue;
-		}
-
-		if (args.verbose) {
-			printf(", write EC %lld\n", ec);
-			fflush(stdout);
-		}
-
-		err = mtd_write(mtd, eb, 0, hdr, write_size);
-		if (err) {
-			if (!args.quiet && !args.verbose)
-				printf("\n");
-			sys_errmsg("cannot write EC header (%d bytes buffer) to eraseblock %d",
-				   write_size, eb);
-			if (args.subpage_size != mtd->min_io_size)
-				normsg("may be %d is incorrect?", args.subpage_size);
-			goto out_free;
-		}
-	}
-
-	if (!args.quiet && !args.verbose)
-		printf("\n");
-
-	if (!novtbl) {
-		if (eb1 == -1 || eb2 == -1) {
-			errmsg("no eraseblocks for volume table");
-			goto out_free;
-		}
-
-		verbose(args.verbose, "write volume table to eraseblocks %d and %d", eb1, eb2);
-		vtbl = ubigen_create_empty_vtbl(ui);
-		if (!vtbl)
-			goto out_free;
-
-		err = ubigen_write_layout_vol(ui, eb1, eb2, ec1,  ec2, vtbl, mtd->fd);
-		free(vtbl);
-		if (err) {
-			errmsg("cannot write layout volume");
-			goto out_free;
-		}
-	}
-
-	free(hdr);
-	return 0;
-
-out_free:
-	free(hdr);
-	return -1;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err, verbose;
-	struct mtd_info mtd;
-	libubi_t libubi;
-	struct ubigen_info ui;
-	struct ubi_scan_info *si;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	err = mtd_get_info(args.node, &mtd);
-	if (err)
-		return errmsg("cannot get information about \"%s\"", args.node);
-
-	if (args.subpage_size == 0)
-		args.subpage_size = mtd.min_io_size;
-	else {
-		if (args.subpage_size > mtd.min_io_size) {
-			errmsg("sub-page cannot be larger than min. I/O unit");
-			goto out_close;
-		}
-
-		if (mtd.min_io_size % args.subpage_size) {
-			errmsg("min. I/O unit size should be multiple of sub-page size");
-			goto out_close;
-		}
-	}
-
-	/* Validate VID header offset if it was specified */
-	if (args.vid_hdr_offs != 0) {
-		if (args.vid_hdr_offs % 8) {
-			errmsg("VID header offset has to be multiple of min. I/O unit size");
-			goto out_close;
-		}
-		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE > mtd.eb_size) {
-			errmsg("bad VID header offset");
-			goto out_close;
-		}
-	}
-
-	/*
-	 * Because of MTD interface limitations 'mtd_get_info()' cannot get
-	 * sub-page so we force the user to pass it via the command line. Let's
-	 * hope the user passed us something sane.
-	 */
-	mtd.subpage_size = args.subpage_size;
-
-	if (mtd.rdonly) {
-		errmsg("mtd%d (%s) is a read-only device", mtd.num, args.node);
-		goto out_close;
-	}
-
-	/* Make sure this MTD device is not attached to UBI */
-	libubi = libubi_open(0);
-	if (libubi) {
-		int ubi_dev_num;
-
-		err = mtd_num2ubi_dev(libubi, mtd.num, &ubi_dev_num);
-		libubi_close(libubi);
-		if (!err) {
-			errmsg("please, first detach mtd%d (%s) from ubi%d",
-			       mtd.num, args.node, ubi_dev_num);
-			goto out_close;
-		}
-	}
-
-	if (!args.quiet) {
-		normsg_cont("mtd%d (%s), size ", mtd.num, mtd.type_str);
-		ubiutils_print_bytes(mtd.size, 1);
-		printf(", %d eraseblocks of ", mtd.eb_size);
-		ubiutils_print_bytes(mtd.eb_size, 1);
-		printf(", min. I/O size %d bytes\n", mtd.min_io_size);
-	}
-
-	if (args.quiet)
-		verbose = 0;
-	else if (args.verbose)
-		verbose = 2;
-	else
-		verbose = 1;
-	err = ubi_scan(&mtd, &si, verbose);
-	if (err) {
-		errmsg("failed to scan mtd%d (%s)", mtd.num, args.node);
-		goto out_close;
-	}
-
-	if (si->good_cnt == 0) {
-		errmsg("all %d eraseblocks are bad", si->bad_cnt);
-		goto out_free;
-	}
-
-	if (si->good_cnt < 2 && (!args.novtbl || args.image)) {
-		errmsg("too few non-bad eraseblocks (%d) on mtd%d", si->good_cnt, mtd.num);
-		goto out_free;
-	}
-
-	if (!args.quiet) {
-		if (si->ok_cnt)
-			normsg("%d eraseblocks have valid erase counter, mean value is %lld",
-			       si->ok_cnt, si->mean_ec);
-		if (si->empty_cnt)
-			normsg("%d eraseblocks are supposedly empty", si->empty_cnt);
-		if (si->corrupted_cnt)
-			normsg("%d corrupted erase counters", si->corrupted_cnt);
-		print_bad_eraseblocks(&mtd, si);
-	}
-
-	if (si->alien_cnt) {
-		if (!args.yes || !args.quiet)
-			warnmsg("%d of %d eraseblocks contain non-ubifs data",
-				si->alien_cnt, si->good_cnt);
-		if (!args.yes && want_exit()) {
-			if (args.yes && !args.quiet)
-				printf("yes\n");
-			goto out_free;
-		}
-	}
-
-	if (!args.override_ec && si->empty_cnt < si->good_cnt) {
-		int percent = ((double)si->ok_cnt)/si->good_cnt * 100;
-
-		/*
-		 * Make sure the majority of eraseblocks have valid
-		 * erase counters.
-		 */
-		if (percent < 50) {
-			if (!args.yes || !args.quiet)
-				warnmsg("only %d of %d eraseblocks have valid erase counter",
-					si->ok_cnt, si->good_cnt);
-				normsg("erase counter 0 will be used for all eraseblocks");
-				normsg("note, arbitrary erase counter value may be specified using -e option");
-			if (!args.yes && want_exit()) {
-				if (args.yes && !args.quiet)
-					printf("yes\n");
-				goto out_free;
-			}
-			 args.ec = 0;
-			 args.override_ec = 1;
-		} else if (percent < 95) {
-			if (!args.yes || !args.quiet)
-				warnmsg("only %d of %d eraseblocks have valid erase counter",
-					si->ok_cnt, si->good_cnt);
-				normsg("mean erase counter %lld will be used for the rest of eraseblock",
-				       si->mean_ec);
-			if (!args.yes && want_exit()) {
-				if (args.yes && !args.quiet)
-					printf("yes\n");
-				goto out_free;
-			}
-			args.ec = si->mean_ec;
-			args.override_ec = 1;
-		}
-	}
-
-	if (!args.quiet && args.override_ec)
-		normsg("use erase counter %lld for all eraseblocks", args.ec);
-
-	ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, args.subpage_size,
-			 args.vid_hdr_offs, args.ubi_ver);
-
-	if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) {
-		/*
-		 * Hmm, what we read from flash and what we calculated using
-		 * min. I/O unit size and sub-page size differs.
-		 */
-		if (!args.yes || !args.quiet) {
-			warnmsg("VID header and data offsets on flash are %d and %d, "
-				"which is different to calculated offsets %d and %d",
-				si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs,
-				ui.data_offs);
-			normsg_cont("use new offsets %d and %d? (yes/no)  ",
-				    si->vid_hdr_offs, si->data_offs);
-		}
-		if (args.yes || answer_is_yes()) {
-			if (args.yes && !args.quiet)
-				printf("yes\n");
-		} else {
-			ui.vid_hdr_offs = si->vid_hdr_offs;
-			ui.data_offs = si->data_offs;
-		}
-	}
-
-	if (args.image) {
-		err = flash_image(&mtd, si);
-		if (err < 0)
-			goto out_free;
-
-		err = format(&mtd, &ui, si, err, 1);
-		if (err)
-			goto out_free;
-	} else {
-		err = format(&mtd, &ui, si, 0, args.novtbl);
-		if (err)
-			goto out_free;
-	}
-
-	ubi_scan_free(si);
-	close(mtd.fd);
-	return 0;
-
-out_free:
-	ubi_scan_free(si);
-out_close:
-	close(mtd.fd);
-	return -1;
-}
diff --git a/ubi-utils/new-utils/src/ubimkvol.c b/ubi-utils/new-utils/src/ubimkvol.c
deleted file mode 100644
index 820c9d8..0000000
--- a/ubi-utils/new-utils/src/ubimkvol.c
+++ /dev/null
@@ -1,313 +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 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    "ubimkvol"
-
-/* 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;
-	const char *node;
-	int maxavs;
-	/* For deprecated -d option handling */
-	int devn;
-	char dev_name[256];
-};
-
-static struct args args = {
-	.vol_type = UBI_DYNAMIC_VOLUME,
-	.bytes = -1,
-	.lebs = -1,
-	.alignment = 1,
-	.vol_id = UBI_VOL_NUM_AUTO,
-	.devn = -1,
-};
-
-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\n\n"
-"The following is a compatibility option which is deprecated, do not use it\n"
-"-d, --devn=<devn>             UBI device number - may be used instead of the UBI\n"
-"                              device node name in which case the utility assumes\n"
-"                              that the device node is \"/dev/ubi<devn>\"";
-
-
-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' },
-	/* Deprecated -d option */
-	{ .name = "devn",      .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ 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:h?Vmd:", 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 'd':
-			/* Handle deprecated -d option */
-			warnmsg("-d is depricated and will be removed, do not use it");
-			args.devn = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.devn < 0)
-				return errmsg("bad UBI device number: " "\"%s\"", optarg);
-			break;
-
-		case 'N':
-			args.name = optarg;
-			break;
-
-		case 'h':
-		case '?':
-			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;
-		}
-	}
-
-	/* Handle deprecated -d option */
-	if (args.devn != -1) {
-		sprintf(args.dev_name, "/dev/ubi%d", args.devn);
-		args.node = args.dev_name;
-	} else {
-		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(1);
-	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 (dev_info.avail_bytes == 0) {
-		errmsg("UBI device does not have free logical eraseblocks");
-		goto out_libubi;
-	}
-
-	if (args.maxavs) {
-		args.bytes = dev_info.avail_bytes;
-		printf("Set volume size to %lld\n", args.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/new-utils/src/ubinfo.c b/ubi-utils/new-utils/src/ubinfo.c
deleted file mode 100644
index 536ec01..0000000
--- a/ubi-utils/new-utils/src/ubinfo.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright (C) 2007, 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 version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * An utility to get UBI information.
- *
- * Author: Artem Bityutskiy
- */
-
-#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    "ubinfo"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int devn;
-	int vol_id;
-	int all;
-	const char *node;
-};
-
-static struct args args = {
-	.vol_id = -1,
-	.devn = -1,
-	.all = 0,
-	.node = NULL,
-};
-
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
-			 " - a tool to print UBI information.";
-
-static const char *optionsstr =
-"-d, --devn=<UBI device number>  UBI device number to get information about\n"
-"-n, --vol_id=<volume ID>        ID of UBI volume to print information about\n"
-"-a, --all                       print information about all devices and volumes,\n"
-"                                or about all volumes if the UBI device was\n"
-"                                specified\n"
-"-h, --help                      print help message\n"
-"-V, --version                   print program version";
-
-static const char *usage =
-"Usage 1: " PROGRAM_NAME " [-d <UBI device number>] [-n <volume ID>] [-a] [-h] [-V] [--vol_id=<volume ID>]\n"
-"\t\t[--devn <UBI device number>] [--all] [--help] [--version]\n"
-"Usage 2: " PROGRAM_NAME " <UBI device node file name> [-a] [-h] [-V] [--all] [--help] [--version]\n"
-"Usage 3: " PROGRAM_NAME " <UBI volume node file name> [-h] [-V] [--help] [--version]\n\n"
-"Example 1: " PROGRAM_NAME " - (no arguments) print general UBI information\n"
-"Example 2: " PROGRAM_NAME " -d 1 - print information about UBI device number 1\n"
-"Example 3: " PROGRAM_NAME " /dev/ubi0 -a - print information about all volumes of UBI\n"
-"           device /dev/ubi0\n"
-"Example 4: " PROGRAM_NAME " /dev/ubi1_0 - print information about UBI volume /dev/ubi1_0\n"
-"Example 5: " PROGRAM_NAME " -a - print all information\n";
-
-static const struct option long_options[] = {
-	{ .name = "devn",      .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ .name = "vol_id",    .has_arg = 1, .flag = NULL, .val = 'n' },
-	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
-	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key;
-		char *endp;
-
-		key = getopt_long(argc, argv, "an:d:hV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'a':
-			args.all = 1;
-			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 'd':
-			args.devn = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.devn < 0)
-				return errmsg("bad UBI device number: \"%s\"", optarg);
-
-			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 ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc - 1)
-		args.node = argv[optind];
-	else if (optind < argc)
-		return errmsg("more then one UBI devices specified (use -h for help)");
-
-	return 0;
-}
-
-static int translate_dev(libubi_t libubi, const char *node)
-{
-	int err;
-
-	err = ubi_node_type(libubi, node);
-	if (err == -1) {
-		if (errno)
-			return errmsg("unrecognized device node \"%s\"", node);
-		return errmsg("\"%s\" does not correspond to any UBI device or volume", node);
-	}
-
-	if (err == 1) {
-		struct ubi_dev_info dev_info;
-
-		err = ubi_get_dev_info(libubi, node, &dev_info);
-		if (err)
-			return sys_errmsg("cannot get information about UBI device \"%s\"", node);
-
-		args.devn = dev_info.dev_num;
-	} else {
-		struct ubi_vol_info vol_info;
-
-		err = ubi_get_vol_info(libubi, node, &vol_info);
-		if (err)
-			return sys_errmsg("cannot get information about UBI volume \"%s\"", node);
-
-		if (args.vol_id != -1)
-			return errmsg("both volume character device node (\"%s\") and "
-				      "volume ID (%d) are specify, use only one of them"
-				      "(use -h for help)", node, args.vol_id);
-
-		args.devn = vol_info.dev_num;
-		args.vol_id = vol_info.vol_id;
-	}
-
-	return 0;
-}
-
-static int print_vol_info(libubi_t libubi, int dev_num, int vol_id)
-{
-	int err;
-	struct ubi_vol_info vol_info;
-
-	err = ubi_get_vol_info1(libubi, dev_num, vol_id, &vol_info);
-	if (err)
-		return sys_errmsg("cannot get information about UBI volume %d on ubi%d",
-				  vol_id, dev_num);
-
-	printf("Volume ID:   %d (on ubi%d)\n", vol_info.vol_id, vol_info.dev_num);
-	printf("Type:        %s\n",
-	       vol_info.type == UBI_DYNAMIC_VOLUME ?  "dynamic" : "static");
-	printf("Alignment:   %d\n", vol_info.alignment);
-
-	printf("Size:        %d LEBs (", vol_info.rsvd_lebs);
-	ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
-	printf(")\n");
-
-	if (vol_info.type == UBI_STATIC_VOLUME) {
-		printf("Data bytes:  ");
-		ubiutils_print_bytes(vol_info.data_bytes, 1);
-		printf("\n");
-	}
-	printf("State:       %s\n", vol_info.corrupted ? "corrupted" : "OK");
-	printf("Name:        %s\n", vol_info.name);
-	printf("Character device major/minor: %d:%d\n",
-	       vol_info.major, vol_info.minor);
-
-	return 0;
-}
-
-static int print_dev_info(libubi_t libubi, int dev_num, int all)
-{
-	int i, err, first = 1;
-	struct ubi_dev_info dev_info;
-	struct ubi_vol_info vol_info;
-
-	err = ubi_get_dev_info1(libubi, dev_num, &dev_info);
-	if (err)
-		return sys_errmsg("cannot get information about UBI device %d", dev_num);
-
-	printf("ubi%d:\n", dev_info.dev_num);
-	printf("Volumes count:                           %d\n", dev_info.vol_count);
-	printf("Logical eraseblock size:                 %d\n", dev_info.leb_size);
-
-	printf("Total amount of logical eraseblocks:     %d (", dev_info.total_lebs);
-	ubiutils_print_bytes(dev_info.total_bytes, 0);
-	printf(")\n");
-
-	printf("Amount of available logical eraseblocks: %d (", dev_info.avail_lebs);
-	ubiutils_print_bytes(dev_info.avail_bytes, 0);
-	printf(")\n");
-
-	printf("Maximum count of volumes                 %d\n", dev_info.max_vol_count);
-	printf("Count of bad physical eraseblocks:       %d\n", dev_info.bad_count);
-	printf("Count of reserved physical eraseblocks:  %d\n", dev_info.bad_rsvd);
-	printf("Current maximum erase counter value:     %lld\n", dev_info.max_ec);
-	printf("Minimum input/output unit size:          %d bytes\n", dev_info.min_io_size);
-	printf("Character device major/minor:            %d:%d\n",
-	       dev_info.major, dev_info.minor);
-
-	if (dev_info.vol_count == 0)
-		return 0;
-
-	printf("Present volumes:                         ");
-	for (i = dev_info.lowest_vol_id;
-	     i <= dev_info.highest_vol_id; i++) {
-		err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-
-			return sys_errmsg("libubi failed to probe volume %d on ubi%d",
-					  i, dev_info.dev_num);
-		}
-
-		if (!first)
-			printf(", %d", i);
-		else {
-			printf("%d", i);
-			first = 0;
-		}
-	}
-	printf("\n");
-
-	if (!all)
-		return 0;
-
-	first = 1;
-	printf("\n");
-
-	for (i = dev_info.lowest_vol_id;
-	     i <= dev_info.highest_vol_id; i++) {
-		if(!first)
-			printf("-----------------------------------\n");
-		err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-
-			return sys_errmsg("libubi failed to probe volume %d on ubi%d",
-					  i, dev_info.dev_num);
-		}
-		first = 0;
-
-		err = print_vol_info(libubi, dev_info.dev_num, i);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
-static int print_general_info(libubi_t libubi, int all)
-{
-	int i, err, first = 1;
-	struct ubi_info ubi_info;
-	struct ubi_dev_info dev_info;
-
-	err = ubi_get_info(libubi, &ubi_info);
-	if (err)
-		return sys_errmsg("cannot get UBI information");
-
-	printf("UBI version:                    %d\n", ubi_info.version);
-	printf("Count of UBI devices:           %d\n", ubi_info.dev_count);
-	if (ubi_info.ctrl_major != -1)
-		printf("UBI control device major/minor: %d:%d\n",
-		       ubi_info.ctrl_major, ubi_info.ctrl_minor);
-	else
-		printf("UBI control device is not supported by this kernel\n");
-
-	if (ubi_info.dev_count == 0)
-		return 0;
-
-	printf("Present UBI devices:            ");
-	for (i = ubi_info.lowest_dev_num;
-	     i <= ubi_info.highest_dev_num; i++) {
-		err = ubi_get_dev_info1(libubi, i, &dev_info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-
-			return sys_errmsg("libubi failed to probe UBI device %d", i);
-		}
-
-		if (!first)
-			printf(", ubi%d", i);
-		else {
-			printf("ubi%d", i);
-			first = 0;
-		}
-	}
-	printf("\n");
-
-	if (!all)
-		return 0;
-
-	first = 1;
-	printf("\n");
-
-	for (i = ubi_info.lowest_dev_num;
-	     i <= ubi_info.highest_dev_num; i++) {
-		if(!first)
-			printf("\n===================================\n\n");
-		err = ubi_get_dev_info1(libubi, i, &dev_info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-
-			return sys_errmsg("libubi failed to probe UBI device %d", i);
-		}
-		first = 0;
-
-		err = print_dev_info(libubi, i, all);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	if (!args.node && args.devn != -1)
-		return errmsg("specify either device number or node file (use -h for help)");
-
-	libubi = libubi_open(1);
-	if (libubi == NULL)
-		return sys_errmsg("cannot open libubi");
-
-	if (args.node) {
-		/*
-		 * A character device was specified, translate this into UBI
-		 * device number and volume ID.
-		 */
-		err = translate_dev(libubi, args.node);
-		if (err)
-			goto out_libubi;
-	}
-
-	if (args.vol_id != -1 && args.devn == -1) {
-		errmsg("volume ID is specified, but UBI device number is not "
-		       "(use -h for help)\n");
-		goto out_libubi;
-	}
-
-	if (args.devn != -1 && args.vol_id != -1) {
-		print_vol_info(libubi, args.devn, args.vol_id);
-		goto out;
-	}
-
-	if (args.devn == -1 && args.vol_id == -1)
-		err = print_general_info(libubi, args.all);
-	else if (args.devn != -1 && args.vol_id == -1)
-		err = print_dev_info(libubi, args.devn, args.all);
-
-	if (err)
-		goto out_libubi;
-
-out:
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/new-utils/src/ubinize.c b/ubi-utils/new-utils/src/ubinize.c
deleted file mode 100644
index 0762aa8..0000000
--- a/ubi-utils/new-utils/src/ubinize.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation
- * 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.
- */
-
-/*
- * Generate UBI images.
- *
- * Authors: Artem Bityutskiy
- *          Oliver Lohmann
- */
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <mtd/ubi-media.h>
-#include <libubigen.h>
-#include <libiniparser.h>
-#include "common.h"
-
-#define PROGRAM_VERSION "1.1"
-#define PROGRAM_NAME    "ubinize"
-
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
-" - a tool to generate UBI images. An UBI image may contain one or more UBI "
-"volumes which have to be defined in the input configuration ini-file. The "
-"ini file defines all the UBI volumes - their characteristics and the and the "
-"contents, but it does not define the characteristics of the flash the UBI "
-"image is generated for. Instead, the flash characteristics are defined via "
-"the command-line options. Note, if not sure about some of the command-line "
-"parameters, do not specify them and let the utility to use default values.";
-
-static const char *optionsstr =
-"-o, --output=<file name>     output file name\n"
-"-p, --peb-size=<bytes>       size of the physical eraseblock of the flash\n"
-"                             this UBI image is created for in bytes,\n"
-"                             kilobytes (KiB), or megabytes (MiB)\n"
-"                             (mandatory parameter)\n"
-"-m, --min-io-size=<bytes>    minimum input/output unit size of the flash\n"
-"                             in bytes\n"
-"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
-"                             headers, e.g. sub-page size in case of NAND\n"
-"                             flash (equivalent to the minimum input/output\n"
-"                             unit size by default)\n"
-"-O, --vid-hdr-offset=<num>   offset if the VID header from start of the\n"
-"                             physical eraseblock (default is the next\n"
-"                             minimum I/O unit or sub-page after the EC\n"
-"                             header)\n"
-"-e, --erase-counter=<num>    the erase counter value to put to EC headers\n"
-"                             (default is 0)\n"
-"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
-"                             (default is 1)\n"
-"-v, --verbose                be verbose\n"
-"-h, --help                   print help message\n"
-"-V, --version                print program version";
-
-static const char *usage =
-"Usage: " PROGRAM_NAME " [-o filename] [-h] [-V] [--output=<filename>] [--help]\n"
-"\t\t[--version] ini-file\n"
-"Example: " PROGRAM_NAME " -o ubi.img -p 16KiB -m 512 -s 256 cfg.ini - create UBI image\n"
-"         'ubi.img' as described by configuration file 'cfg.ini'";
-
-static const char *ini_doc = "INI-file format.\n"
-"The input configuration ini-file describes all the volumes which have to\n"
-"be included to the output UBI image. Each volume is described in its own\n"
-"section which may be named arbitrarily. The section consists on\n"
-"\"key=value\" pairs, for example:\n\n"
-"[jffs2-volume]\n"
-"mode=ubi\n"
-"image=../jffs2.img\n"
-"vol_id=1\n"
-"vol_size=30MiB\n"
-"vol_type=dynamic\n"
-"vol_name=jffs2_volume\n"
-"vol_flags=autoresize\n"
-"vol_alignment=1\n\n"
-"This example configuration file tells the utility to create an UBI image\n"
-"with one volume with ID 1, volume size 30MiB, the volume is dynamic, has\n"
-"name \"jffs2_volume\", \"autoresize\" volume flag, and alignment 1. The\n"
-"\"image=../jffs2.img\" line tells the utility to take the contents of the\n"
-"volume from the \"../jffs2.img\" file. The size of the image file has to be\n"
-"less or equivalent to the volume size (30MiB). The \"mode=ubi\" line is\n"
-"mandatory and just tells that the section describes an UBI volume - other\n"
-"section modes may be added in the future.\n"
-"Notes:\n"
-"  * size in vol_size might be specified kilobytes (KiB), megabytes (MiB),\n"
-"    gigabytes (GiB) or bytes (no modifier);\n"
-"  * if \"vol_size\" key is absent, the volume size is assumed to be\n"
-"    equivalent to the size of the image file (defined by \"image\" key);\n"
-"  * if the \"image\" is absent, the volume is assumed to be empty;\n"
-"  * volume alignment must not be greater than the logical eraseblock size;\n"
-"  * one ini file may contain arbitrary number of sections, the utility will\n"
-"    put all the volumes which are described by these section to the output\n"
-"    UBI image file.";
-
-struct option long_options[] = {
-	{ .name = "output",         .has_arg = 1, .flag = NULL, .val = 'o' },
-	{ .name = "peb-size",       .has_arg = 1, .flag = NULL, .val = 'p' },
-	{ .name = "min-io-size",    .has_arg = 1, .flag = NULL, .val = 'm' },
-	{ .name = "sub-page-size",  .has_arg = 1, .flag = NULL, .val = 's' },
-	{ .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
-	{ .name = "erase-counter",  .has_arg = 1, .flag = NULL, .val = 'e' },
-	{ .name = "ubi-ver",        .has_arg = 1, .flag = NULL, .val = 'x' },
-	{ .name = "verbose",        .has_arg = 0, .flag = NULL, .val = 'v' },
-	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0}
-};
-
-struct args {
-	const char *f_in;
-	const char *f_out;
-	int out_fd;
-	int peb_size;
-	int min_io_size;
-	int subpage_size;
-	int vid_hdr_offs;
-	int ec;
-	int ubi_ver;
-	int verbose;
-	dictionary *dict;
-};
-
-static struct args args = {
-	.peb_size     = -1,
-	.min_io_size  = -1,
-	.subpage_size = -1,
-	.ubi_ver      = 1,
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key;
-		char *endp;
-
-		key = getopt_long(argc, argv, "o:p:m:s:O:e:x:vhV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'o':
-			args.out_fd = open(optarg, O_CREAT | O_TRUNC | O_WRONLY,
-					   S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP | S_IROTH);
-			if (args.out_fd == -1)
-				return sys_errmsg("cannot open file \"%s\"", optarg);
-			args.f_out = optarg;
-			break;
-
-		case 'p':
-			args.peb_size = ubiutils_get_bytes(optarg);
-			if (args.peb_size <= 0)
-				return errmsg("bad physical eraseblock size: \"%s\"", optarg);
-			break;
-
-		case 'm':
-			args.min_io_size = ubiutils_get_bytes(optarg);
-			if (args.min_io_size <= 0)
-				return errmsg("bad min. I/O unit size: \"%s\"", optarg);
-			if (!is_power_of_2(args.min_io_size))
-				return errmsg("min. I/O unit size should be power of 2");
-			break;
-
-		case 's':
-			args.subpage_size = ubiutils_get_bytes(optarg);
-			if (args.subpage_size <= 0)
-				return errmsg("bad sub-page size: \"%s\"", optarg);
-			if (!is_power_of_2(args.subpage_size))
-				return errmsg("sub-page size should be power of 2");
-			break;
-
-		case 'O':
-			args.vid_hdr_offs = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.vid_hdr_offs < 0)
-				return errmsg("bad VID header offset: \"%s\"", optarg);
-			break;
-
-		case 'e':
-			args.ec = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.ec < 0)
-				return errmsg("bad erase counter value: \"%s\"", optarg);
-			break;
-
-		case 'x':
-			args.ubi_ver = strtoul(optarg, &endp, 0);
-			if (*endp != '\0'  || endp == optarg || args.ubi_ver < 0)
-				return errmsg("bad UBI version: \"%s\"", optarg);
-			break;
-
-		case 'v':
-			args.verbose = 1;
-			break;
-
-		case 'h':
-			ubiutils_print_text(stderr, doc, 80);
-			fprintf(stderr, "\n%s\n\n", ini_doc);
-			fprintf(stderr, "%s\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc)
-		return errmsg("input configuration file was not specified (use -h for help)");
-
-	if (optind != argc - 1)
-		return errmsg("more then one configuration file was specified (use -h for help)");
-
-	args.f_in = argv[optind];
-
-	if (args.peb_size < 0)
-		return errmsg("physical eraseblock size was not specified (use -h for help)");
-
-	if (args.peb_size > 1024*1024)
-		return errmsg("too high physical eraseblock size %d", args.peb_size);
-
-	if (args.min_io_size < 0)
-		return errmsg("min. I/O unit size was not specified (use -h for help)");
-
-	if (args.subpage_size < 0)
-		args.subpage_size = args.min_io_size;
-
-	if (args.subpage_size > args.min_io_size)
-		return errmsg("sub-page cannot be larger then min. I/O unit");
-
-	if (args.peb_size % args.min_io_size)
-		return errmsg("physical eraseblock should be multiple of min. I/O units");
-
-	if (args.min_io_size % args.subpage_size)
-		return errmsg("min. I/O unit size should be multiple of sub-page size");
-
-	if (!args.f_out)
-		return errmsg("output file was not specified (use -h for help)");
-
-	if (args.vid_hdr_offs) {
-		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE >= args.peb_size)
-			return errmsg("bad VID header position");
-		if (args.vid_hdr_offs % 8)
-			return errmsg("VID header offset has to be multiple of min. I/O unit size");
-	}
-
-	return 0;
-}
-
-static int read_section(const struct ubigen_info *ui, const char *sname,
-			struct ubigen_vol_info *vi, const char **img,
-			struct stat *st)
-{
-	char buf[256];
-	const char *p;
-
-	*img = NULL;
-
-	if (strlen(sname) > 128)
-		return errmsg("too long section name \"%s\"", sname);
-
-	/* Make sure mode is UBI, otherwise ignore this section */
-	sprintf(buf, "%s:mode", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (!p) {
-		errmsg("\"mode\" key not found in section \"%s\"", sname);
-		errmsg("the \"mode\" key is mandatory and has to be "
-		       "\"mode=ubi\" if the section describes an UBI volume");
-		return -1;
-	}
-
-	/* If mode is not UBI, skip this section */
-	if (strcmp(p, "ubi")) {
-		verbose(args.verbose, "skip non-ubi section \"%s\"", sname);
-		return 1;
-	}
-
-	verbose(args.verbose, "mode=ubi, keep parsing");
-
-	/* Fetch volume type */
-	sprintf(buf, "%s:vol_type", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (!p) {
-		normsg("volume type was not specified in "
-		       "section \"%s\", assume \"dynamic\"\n", sname);
-		vi->type = UBI_VID_DYNAMIC;
-	} else {
-		if (!strcmp(p, "static"))
-			vi->type = UBI_VID_STATIC;
-		else if (!strcmp(p, "dynamic"))
-			vi->type = UBI_VID_DYNAMIC;
-		else
-			return errmsg("invalid volume type \"%s\" in section  \"%s\"",
-				      p, sname);
-	}
-
-	verbose(args.verbose, "volume type: %s",
-		vi->type == UBI_VID_DYNAMIC ? "dynamic" : "static");
-
-	/* Fetch the name of the volume image file */
-	sprintf(buf, "%s:image", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (p) {
-		*img = p;
-		if (stat(p, st))
-			return sys_errmsg("cannot stat \"%s\" referred from section \"%s\"",
-					  p, sname);
-		if (st->st_size == 0)
-			return errmsg("empty file \"%s\" referred from section \"%s\"",
-				       p, sname);
-	} else if (vi->type == UBI_VID_STATIC)
-		return errmsg("image is not specified for static volume in section \"%s\"",
-			      sname);
-
-	/* Fetch volume id */
-	sprintf(buf, "%s:vol_id", sname);
-	vi->id = iniparser_getint(args.dict, buf, -1);
-	if (vi->id == -1)
-		return errmsg("\"vol_id\" key not found in section  \"%s\"", sname);
-	if (vi->id < 0)
-		return errmsg("negative volume ID %d in section \"%s\"",
-			      vi->id, sname);
-	if (vi->id >= ui->max_volumes)
-		return errmsg("too high volume ID %d in section \"%s\", max. is %d",
-			      vi->id, sname, ui->max_volumes);
-
-	verbose(args.verbose, "volume ID: %d", vi->id);
-
-	/* Fetch volume size */
-	sprintf(buf, "%s:vol_size", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (p) {
-		vi->bytes = ubiutils_get_bytes(p);
-		if (vi->bytes <= 0)
-			return errmsg("bad \"vol_size\" key value \"%s\" (section \"%s\")",
-				      p, sname);
-
-		/* Make sure the image size is not larger than volume size */
-		if (*img && st->st_size > vi->bytes)
-			return errmsg("error in section \"%s\": size of the image file "
-				      "\"%s\" is %lld, which is larger than volume size %lld",
-				      sname, *img, (long long)st->st_size, vi->bytes);
-		verbose(args.verbose, "volume size: %lld bytes", vi->bytes);
-	} else {
-		struct stat st;
-
-		if (!*img)
-			return errmsg("neither image file (\"image=\") nor volume size "
-				      "(\"vol_size=\") specified in section \"%s\"", sname);
-
-		if (stat(*img, &st))
-			return sys_errmsg("cannot stat \"%s\"", *img);
-
-		vi->bytes = st.st_size;
-
-		if (vi->bytes == 0)
-			return errmsg("file \"%s\" referred from section \"%s\" is empty",
-				      *img, sname);
-
-		normsg_cont("volume size was not specified in section \"%s\", assume"
-			    " minimum to fit image \"%s\"", sname, *img);
-		ubiutils_print_bytes(vi->bytes, 1);
-		printf("\n");
-	}
-
-	/* Fetch volume name */
-	sprintf(buf, "%s:vol_name", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (!p)
-		return errmsg("\"vol_name\" key not found in section \"%s\"", sname);
-
-	vi->name = p;
-	vi->name_len = strlen(p);
-	if (vi->name_len > UBI_VOL_NAME_MAX)
-		return errmsg("too long volume name in section \"%s\", max. is %d characters",
-			      vi->name, UBI_VOL_NAME_MAX);
-
-	verbose(args.verbose, "volume name: %s", p);
-
-	/* Fetch volume alignment */
-	sprintf(buf, "%s:vol_alignment", sname);
-	vi->alignment = iniparser_getint(args.dict, buf, -1);
-	if (vi->alignment == -1)
-		vi->alignment = 1;
-	else if (vi->id < 0)
-		return errmsg("negative volume alignement %d in section \"%s\"",
-			      vi->alignment, sname);
-
-	verbose(args.verbose, "volume alignment: %d", vi->alignment);
-
-	/* Fetch volume flags */
-	sprintf(buf, "%s:vol_flags", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (p) {
-		if (!strcmp(p, "autoresize")) {
-			verbose(args.verbose, "autoresize flags found");
-			vi->flags |= UBI_VTBL_AUTORESIZE_FLG;
-		} else {
-			return errmsg("unknown flags \"%s\" in section \"%s\"",
-				      p, sname);
-		}
-	}
-
-	/* Initialize the rest of the volume information */
-	vi->data_pad = ui->leb_size % vi->alignment;
-	vi->usable_leb_size = ui->leb_size - vi->data_pad;
-	if (vi->type == UBI_VID_DYNAMIC)
-		vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size;
-	else
-		vi->used_ebs = (st->st_size + vi->usable_leb_size - 1) / vi->usable_leb_size;
-	vi->compat = 0;
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err = -1, sects, i, autoresize_was_already = 0;
-	struct ubigen_info ui;
-	struct ubi_vtbl_record *vtbl;
-	struct ubigen_vol_info *vi;
-	off_t seek;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	ubigen_info_init(&ui, args.peb_size, args.min_io_size,
-			 args.subpage_size, args.vid_hdr_offs,
-			 args.ubi_ver);
-
-	verbose(args.verbose, "LEB size:      %d", ui.leb_size);
-	verbose(args.verbose, "PEB size:      %d", ui.peb_size);
-	verbose(args.verbose, "min. I/O size: %d", ui.min_io_size);
-	verbose(args.verbose, "sub-page size: %d", args.subpage_size);
-	verbose(args.verbose, "VID offset:    %d", ui.vid_hdr_offs);
-	verbose(args.verbose, "data offset:   %d", ui.data_offs);
-
-	vtbl = ubigen_create_empty_vtbl(&ui);
-	if (!vtbl)
-		goto out;
-
-	args.dict = iniparser_load(args.f_in);
-	if (!args.dict) {
-		errmsg("cannot load the input ini file \"%s\"", args.f_in);
-		goto out_vtbl;
-	}
-
-	verbose(args.verbose, "loaded the ini-file \"%s\"", args.f_in);
-
-	/* Each section describes one volume */
-	sects = iniparser_getnsec(args.dict);
-	if (sects == -1) {
-		errmsg("ini-file parsing error (iniparser_getnsec)");
-		goto out_dict;
-	}
-
-	verbose(args.verbose, "count of sections: %d", sects);
-	if (sects == 0) {
-		errmsg("no sections found the ini-file \"%s\"", args.f_in);
-		goto out_dict;
-	}
-
-	if (sects > ui.max_volumes) {
-		errmsg("too many sections (%d) in the ini-file \"%s\"",
-		       sects, args.f_in);
-		normsg("each section corresponds to an UBI volume, maximum "
-		       "count of volumes is %d", ui.max_volumes);
-		goto out_dict;
-	}
-
-	vi = calloc(sizeof(struct ubigen_vol_info), sects);
-	if (!vi) {
-		errmsg("cannot allocate memory");
-		goto out_dict;
-	}
-
-	/*
-	 * Skip 2 PEBs at the beginning of the file for the volume table which
-	 * will be written later.
-	 */
-	seek = ui.peb_size * 2;
-	if (lseek(args.out_fd, seek, SEEK_SET) != seek) {
-		sys_errmsg("cannot seek file \"%s\"", args.f_out);
-		goto out_free;
-	}
-
-	for (i = 0; i < sects; i++) {
-		const char *sname = iniparser_getsecname(args.dict, i);
-		const char *img = NULL;
-		struct stat st;
-		int fd, j;
-
-		if (!sname) {
-			errmsg("ini-file parsing error (iniparser_getsecname)");
-			goto out_free;
-		}
-
-		if (args.verbose)
-			printf("\n");
-		verbose(args.verbose, "parsing section \"%s\"", sname);
-
-		err = read_section(&ui, sname, &vi[i], &img, &st);
-		if (err == -1)
-			goto out_free;
-
-		verbose(args.verbose, "adding volume %d", vi[i].id);
-
-		/*
-		 * Make sure that volume ID and name is unique and that only
-		 * one volume has auto-resize flag
-		 */
-		for (j = 0; j < i; j++) {
-			if (vi[i].id == vi[j].id) {
-				errmsg("volume IDs must be unique, but ID %d "
-				       "in section \"%s\" is not",
-				       vi[i].id, sname);
-				goto out_free;
-			}
-
-			if (!strcmp(vi[i].name, vi[j].name)) {
-				errmsg("volume name must be unique, but name "
-				       "\"%s\" in section \"%s\" is not",
-				       vi[i].name, sname);
-				goto out_free;
-			}
-		}
-
-		if (vi[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
-			if (autoresize_was_already)
-				return errmsg("only one volume is allowed "
-					      "to have auto-resize flag");
-			autoresize_was_already = 1;
-		}
-
-		err = ubigen_add_volume(&ui, &vi[i], vtbl);
-		if (err) {
-			errmsg("cannot add volume for section \"%s\"", sname);
-			goto out_free;
-		}
-
-		if (img) {
-			fd = open(img, O_RDONLY);
-			if (fd == -1) {
-				sys_errmsg("cannot open \"%s\"", img);
-				goto out_free;
-			}
-
-			verbose(args.verbose, "writing volume %d", vi[i].id);
-			verbose(args.verbose, "image file: %s", img);
-
-			err = ubigen_write_volume(&ui, &vi[i], args.ec, st.st_size, fd, args.out_fd);
-			close(fd);
-			if (err) {
-				errmsg("cannot write volume for section \"%s\"", sname);
-				goto out_free;
-			}
-		}
-
-		if (args.verbose)
-			printf("\n");
-	}
-
-	verbose(args.verbose, "writing layout volume");
-
-	err = ubigen_write_layout_vol(&ui, 0, 1, args.ec, args.ec, vtbl, args.out_fd);
-	if (err) {
-		errmsg("cannot write layout volume");
-		goto out_free;
-	}
-
-	verbose(args.verbose, "done");
-
-	free(vi);
-	iniparser_freedict(args.dict);
-	free(vtbl);
-	close(args.out_fd);
-	return 0;
-
-out_free:
-	free(vi);
-out_dict:
-	iniparser_freedict(args.dict);
-out_vtbl:
-	free(vtbl);
-out:
-	close(args.out_fd);
-	remove(args.f_out);
-	return err;
-}
diff --git a/ubi-utils/new-utils/src/ubirename.c b/ubi-utils/new-utils/src/ubirename.c
deleted file mode 100644
index 8f33718..0000000
--- a/ubi-utils/new-utils/src/ubirename.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2008 Logitech.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * An utility to get rename UBI volumes.
- *
- * Author: Richard Titmuss
- */
-
-#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    "ubirename"
-
-static const char *usage =
-"Usage: " PROGRAM_NAME " <UBI device node file name> [<old name> <new name>|...]\n\n"
-"Example: " PROGRAM_NAME "/dev/ubi0 A B C D - rename volume A to B, and C to D\n\n"
-"This utility allows re-naming several volumes in one go atomically.\n"
-"For example, if you have volumes A and B, then you may rename A into B\n"
-"and B into A at one go, and the operation will be atomic. This allows\n"
-"implementing atomic UBI volumes upgrades. E.g., if you have volume A\n"
-"and want to upgrade it atomically, you create a temporary volume B,\n"
-"put your new data to B, then rename A to B and B to A, and then you\n"
-"may remove old volume B.\n"
-"It is also allowed to re-name multiple volumes at a time, but 16 max.\n"
-"renames at once, which means you may specify up to 32 volume names.\n"
-"If you have volumes A and B, and re-name A to B, bud do not re-name\n"
-"B to something else in the same request, old volume B will be removed\n"
-"and A will be renamed into B.\n";
-
-static int get_vol_id(libubi_t libubi, struct ubi_dev_info *dev_info,
-		       char *name)
-{
-	int err, i;
-	struct ubi_vol_info vol_info;
-
-	for (i=dev_info->lowest_vol_id; i<=dev_info->highest_vol_id; i++) {
-		err = ubi_get_vol_info1(libubi, dev_info->dev_num, i, &vol_info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (strcmp(name, vol_info.name) == 0)
-			return vol_info.vol_id;
-	}
-
-	return -1;
-}
-
-int main(int argc, char * const argv[])
-{
-	int i, err;
-	int count = 0;
-	libubi_t libubi;
-	struct ubi_dev_info dev_info;
-	struct ubi_rnvol_req rnvol;
-	const char *node;
-
-	if (argc < 3 || (argc & 1) == 1) {
-		errmsg("too few arguments");
-		fprintf(stderr, "%s\n", usage);
-		return -1;
-	}
-
-	if (argc > UBI_MAX_RNVOL + 2) {
-		errmsg("too many volumes to re-name, max. is %d",
-		       UBI_MAX_RNVOL);
-		return -1;
-	}
-
-	node = argv[1];
-	libubi = libubi_open(1);
-	if (!libubi)
-		return sys_errmsg("cannot open libubi");
-
-	err = ubi_node_type(libubi, node);
-	if (err == 2) {
-		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
-		       node);
-		goto out_libubi;
-	} else if (err < 0) {
-		errmsg("\"%s\" is not an UBI device node", node);
-		goto out_libubi;
-	}
-
-	err = ubi_get_dev_info(libubi, node, &dev_info);
-	if (err == -1) {
-		sys_errmsg("cannot get information about UBI device \"%s\"", node);
-		goto out_libubi;
-	}
-
-	for (i = 2; i < argc; i += 2) {
-		err = get_vol_id(libubi, &dev_info, argv[i]);
-		if (err == -1) {
-			errmsg("\"%s\" volume not found", argv[i]);
-			goto out_libubi;
-		}
-
-		rnvol.ents[count].vol_id = err;
-		rnvol.ents[count].name_len = strlen(argv[i + 1]);
-		strcpy(rnvol.ents[count++].name, argv[i + 1]);
-	}
-
-	rnvol.count = count;
-
-	err = ubi_rnvols(libubi, node, &rnvol);
-	if (err == -1) {
-		sys_errmsg("cannot rename volumes");
-		goto out_libubi;
-	}
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/new-utils/src/ubirmvol.c b/ubi-utils/new-utils/src/ubirmvol.c
deleted file mode 100644
index a4cf1df..0000000
--- a/ubi-utils/new-utils/src/ubirmvol.c
+++ /dev/null
@@ -1,230 +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 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    "ubirmvol"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int vol_id;
-	const char *node;
-	const char *name;
-	/* For deprecated -d option handling */
-	int devn;
-	char dev_name[256];
-};
-
-static struct args args = {
-	.vol_id = -1,
-	.devn = -1,
-};
-
-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"
-"-N, --name=<volume name>   volume name to remove\n"
-"-h, -?, --help             print help message\n"
-"-V, --version              print program version\n\n"
-"The following is a compatibility option which is deprecated, do not use it\n"
-"-d, --devn=<devn>          UBI device number - may be used instead of the UBI\n"
-"                           device node name in which case the utility assumes\n"
-"                           that the device node is \"/dev/ubi<devn>\"";
-
-static const char *usage =
-"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>]\n\n"
-"         [-N <volume name>] [--name=<volume name>] [-h] [--help]\n\n"
-"Example: " PROGRAM_NAME "/dev/ubi0 -n 1 - remove UBI volume 1 from UBI device corresponding\n"
-"         to /dev/ubi0\n"
-"         " PROGRAM_NAME "/dev/ubi0 -N my_vol - remove UBI named \"my_vol\" from UBI device\n"
-"         corresponding to /dev/ubi0";
-
-static const struct option long_options[] = {
-	{ .name = "vol_id",  .has_arg = 1, .flag = NULL, .val = 'n' },
-	{ .name = "name",    .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' },
-	/* Deprecated -d option */
-	{ .name = "devn",    .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int param_sanity_check(void)
-{
-	if (args.vol_id == -1 && !args.name) {
-		errmsg("please, specify either volume ID or volume name");
-		return -1;
-	}
-
-	if (args.vol_id != -1 && args.name) {
-		errmsg("please, specify either volume ID or volume name, not both");
-		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:N:h?Vd:", 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 'N':
-			args.name = optarg;
-			break;
-
-		case 'h':
-		case '?':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'd':
-			/* Handle deprecated -d option */
-			warnmsg("-d is depricated and will be removed, do not use it");
-			args.devn = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.devn < 0)
-				return errmsg("bad UBI device number: " "\"%s\"", optarg);
-			break;
-
-		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;
-		}
-	}
-
-	/* Handle deprecated -d option */
-	if (args.devn != -1) {
-		sprintf(args.dev_name, "/dev/ubi%d", args.devn);
-		args.node = args.dev_name;
-	} else {
-		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(1);
-	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;
-	}
-
-	if (args.name) {
-		struct ubi_dev_info dev_info;
-		struct ubi_vol_info vol_info;
-
-		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;
-		}
-
-		err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num,
-					   args.name, &vol_info);
-		if (err) {
-			sys_errmsg("cannot find UBI volume \"%s\"", args.name);
-			goto out_libubi;
-		}
-
-		args.vol_id = vol_info.vol_id;
-	}
-
-	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/new-utils/src/ubiupdatevol.c b/ubi-utils/new-utils/src/ubiupdatevol.c
deleted file mode 100644
index c83731c..0000000
--- a/ubi-utils/new-utils/src/ubiupdatevol.c
+++ /dev/null
@@ -1,355 +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 <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.1"
-#define PROGRAM_NAME    "ubiupdatevol"
-
-struct args {
-	int truncate;
-	const char *node;
-	const char *img;
-	/* For deprecated -d and -B options handling */
-	int devn;
-	char dev_name[256];
-	int broken_update;
-	int size;
-	int use_stdin;
-};
-
-static struct args args = {
-	.devn = -1,
-};
-
-static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
-			 " - a tool to write data to UBI volumes.";
-
-static const char *optionsstr =
-"-t, --truncate             truncate volume (wipe it out)\n"
-"-h, --help                 print help message\n"
-"-V, --version              print program version\n\n"
-"-s, --size=<bytes>         bytes in input, if not reading from file\n"
-"The following are compatibility options which are deprecated, do not use them\n"
-"-d, --devn=<devn>          UBI device number - may be used instead of the UBI\n"
-"                           device node name in which case the utility assumes\n"
-"                           that the device node is \"/dev/ubi<devn>\"\n"
-"-B, --broken-update        broken update, this is for testing";
-
-static const char *usage =
-"Usage: " PROGRAM_NAME " <UBI volume node file name> [-t] [-h] [-V] [--truncate] [--size=x] [--help]\n"
-"\t\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' },
-	{ .name = "size",     .has_arg = 1, .flag = NULL, .val = 's' },
-	/* Deprecated -d and -B options */
-	{ .name = "devn",     .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ .name = "broken-update", .has_arg = 1, .flag = NULL, .val = 'B' },
-	{ NULL, 0, NULL, 0}
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key;
-		char *endp;
-
-		key = getopt_long(argc, argv, "n:th?Vd:s:", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 't':
-			args.truncate = 1;
-			break;
-
-		case 's':
-			args.size = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.size < 0)
-				return errmsg("bad size: " "\"%s\"", optarg);
-			break;
-
-		case 'h':
-		case '?':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'd':
-			/* Handle deprecated -d option */
-			warnmsg("-d is depricated and will be removed, do not use it");
-			args.devn = strtoul(optarg, &endp, 0);
-			if (*endp != '\0' || endp == optarg || args.devn < 0)
-				return errmsg("bad UBI device number: " "\"%s\"", optarg);
-			break;
-
-		case 'B':
-			/* Handle deprecated -B option */
-			warnmsg("-B is depricated and will be removed, do not use it");
-			args.broken_update = 1;
-			break;
-
-		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;
-		}
-	}
-
-	/* Handle deprecated -d option */
-	if (args.devn != -1) {
-		sprintf(args.dev_name, "/dev/ubi%d", args.devn);
-		args.node = args.dev_name;
-	} else {
-		if (optind == argc)
-			return errmsg("UBI device name was not specified (use -h for help)");
-		else if (optind != argc - 2 && !args.truncate)
-			return errmsg("specify UBI device name and image file name as first 2 "
-				      "parameters (use -h for help)");
-	}
-
-	args.node = argv[optind];
-	args.img  = argv[optind + 1];
-
-	if (args.img && args.truncate)
-		return errmsg("You can't truncate and specify an image (use -h for help)");
-
-	if (args.img && !args.truncate) {
-		if (strcmp(args.img, "-") == 0)
-			args.use_stdin = 1;
-		if (args.use_stdin && !args.size)
-			return errmsg("file size must be specified if input is stdin");
-	}
-
-	return 0;
-}
-
-static int truncate_volume(libubi_t libubi)
-{
-	int err, fd;
-
-	fd = open(args.node, O_RDWR);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", args.node);
-
-	err = ubi_update_start(libubi, fd, 0);
-	if (err) {
-		sys_errmsg("cannot truncate volume \"%s\"", args.node);
-		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;
-			}
-			return sys_errmsg("cannot write %d bytes to volume \"%s\"",
-					  len, args.node);
-		}
-
-		if (ret == 0)
-			return errmsg("cannot write %d bytes to volume \"%s\"", len, args.node);
-
-		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;
-	char *buf;
-
-	buf = malloc(vol_info->leb_size);
-	if (!buf)
-		return errmsg("cannot allocate %d bytes of memory", vol_info->leb_size);
-
-	if (!args.size) {
-		struct stat st;
-		err = stat(args.img, &st);
-		if (err < 0) {
-			errmsg("stat failed on \"%s\"", args.img);
-			goto out_free;
-		}
-
-		bytes = st.st_size;
-	} else
-		bytes = args.size;
-
-	if (bytes > vol_info->rsvd_bytes) {
-		errmsg("\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)",
-		       args.img, bytes, args.node, vol_info->rsvd_bytes);
-		goto out_free;
-	}
-
-	/* A hack to handle deprecated -B option */
-	if (args.broken_update)
-		bytes = 1;
-
-	fd = open(args.node, O_RDWR);
-	if (fd == -1) {
-		sys_errmsg("cannot open UBI volume \"%s\"", args.node);
-		goto out_free;
-	}
-
-	if (args.use_stdin)
-		ifd = STDIN_FILENO;
-	else {
-		ifd = open(args.img, O_RDONLY);
-		if (ifd == -1) {
-			sys_errmsg("cannot open \"%s\"", args.img);
-			goto out_close1;
-		}
-	}
-
-	err = ubi_update_start(libubi, fd, bytes);
-	if (err) {
-		sys_errmsg("cannot start volume \"%s\" update", args.node);
-		goto out_close;
-	}
-
-	while (bytes) {
-		int ret, to_copy = vol_info->leb_size;
-
-		if (to_copy > bytes)
-			to_copy = bytes;
-
-		ret = read(ifd, buf, to_copy);
-		if (ret <= 0) {
-			if (errno == EINTR) {
-				warnmsg("do not interrupt me!");
-				continue;
-			} else {
-				sys_errmsg("cannot read %d bytes from \"%s\"",
-						to_copy, args.img);
-				goto out_close;
-			}
-		}
-
-		err = ubi_write(fd, buf, ret);
-		if (err)
-			goto out_close;
-		bytes -= ret;
-	}
-
-	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;
-
-	libubi = libubi_open(1);
-	if (libubi == NULL) {
-		sys_errmsg("cannot open libubi");
-		goto out_libubi;
-	}
-
-	err = ubi_node_type(libubi, args.node);
-	if (err == 1) {
-		errmsg("\"%s\" is an UBI device node, not an UBI volume node",
-		       args.node);
-		goto out_libubi;
-	} else if (err < 0) {
-		errmsg("\"%s\" is not an UBI volume node", args.node);
-		goto out_libubi;
-	}
-
-	err = ubi_get_vol_info(libubi, args.node, &vol_info);
-	if (err) {
-		sys_errmsg("cannot get information about UBI volume \"%s\"",
-			   args.node);
-		goto out_libubi;
-	}
-
-	if (args.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-utils/.gitignore b/ubi-utils/old-utils/.gitignore
new file mode 100644
index 0000000..83e8b71
--- /dev/null
+++ b/ubi-utils/old-utils/.gitignore
@@ -0,0 +1,9 @@
+/bin2nand
+/mkbootenv
+/nand2bin
+/pddcustomize
+/pfi2bin
+/pfiflash
+/ubigen
+/ubimirror
+/unubi
diff --git a/ubi-utils/old-utils/Makefile b/ubi-utils/old-utils/Makefile
new file mode 100644
index 0000000..5d20592
--- /dev/null
+++ b/ubi-utils/old-utils/Makefile
@@ -0,0 +1,59 @@
+#
+# Makefile for ubi-utils
+#
+
+KERNELHDR := ../../include
+
+CFLAGS ?= -O2 -g -Werror
+CPPFLAGS += -I./inc -I./src -I$(KERNELHDR) \
+	-std=gnu99 -DPACKAGE_VERSION=\"1.0\"
+
+PERLPROGS = mkpfi ubicrc32.pl
+
+TARGETS = pfiflash pddcustomize ubimirror bin2nand nand2bin ubigen \
+	mkbootenv unubi pfi2bin
+
+vpath   %.c ./src
+
+include ../../common.mk
+
+$(BUILDDIR)/pddcustomize: $(addprefix $(BUILDDIR)/,\
+	pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \
+	libubi.o crc32.o)
+
+$(BUILDDIR)/pfiflash: $(addprefix $(BUILDDIR)/,\
+	pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \
+	bootenv.o hashmap.o pfi.o libubi.o crc32.o)
+
+$(BUILDDIR)/ubimirror: $(addprefix $(BUILDDIR)/,\
+	ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \
+	libubi.o crc32.o)
+
+$(BUILDDIR)/nand2bin: $(addprefix $(BUILDDIR)/,\
+	nand2bin.o nandecc.o nandcorr.o)
+
+$(BUILDDIR)/bin2nand: $(addprefix $(BUILDDIR)/,\
+	bin2nand.o error.o nandecc.o)
+
+$(BUILDDIR)/ubigen: $(addprefix $(BUILDDIR)/,\
+	ubigen.o libubigen.o crc32.o)
+
+$(BUILDDIR)/mkbootenv: $(addprefix $(BUILDDIR)/,\
+	mkbootenv.o bootenv.o hashmap.o error.o crc32.o)
+
+$(BUILDDIR)/unubi: $(addprefix $(BUILDDIR)/,\
+	unubi.o crc32.o unubi_analyze.o eb_chain.o)
+
+$(BUILDDIR)/pfi2bin: $(addprefix $(BUILDDIR)/,\
+	pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \
+	hashmap.o reader.o pfi.o)
+
+install::
+	mkdir -p ${DESTDIR}/${SBINDIR}
+	install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
+	(cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/)
+
+uninstall:
+	for file in ${TARGETS} ${PERLPROGS}; do \
+		$(RM) ${DESTDIR}/${SBINDIR}/$$file; \
+	done
diff --git a/ubi-utils/old-utils/README b/ubi-utils/old-utils/README
new file mode 100644
index 0000000..d976a76
--- /dev/null
+++ b/ubi-utils/old-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-utils/UBI.TXT b/ubi-utils/old-utils/UBI.TXT
new file mode 100644
index 0000000..9a1c3c7
--- /dev/null
+++ b/ubi-utils/old-utils/UBI.TXT
@@ -0,0 +1,108 @@
+UBI - Unsorted Block Images
+
+UBI (Latin: "where?") manages multiple logical volumes on a single
+flash device, specifically supporting NAND flash devices. UBI provides
+a flexible partitioning concept which still allows for wear-levelling
+across the whole flash device.
+
+In a sense, UBI may be compared to the Logical Volume Manager
+(LVM). Whereas LVM maps logical sector numbers to physical HDD sector
+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: 
+http://www.linux-mtd.infradead.org/doc/ubi.html
+
+Partitioning/Re-partitioning
+
+  An UBI volume occupies a certain number of erase blocks. This is
+  limited by a configured maximum volume size, which could also be
+  viewed as the partition size. Each individual UBI volume's size can
+  be changed independently of the other UBI volumes, provided that the
+  sum of all volume sizes doesn't exceed a certain limit.
+
+  UBI supports dynamic volumes and static volumes. Static volumes are
+  read-only and their contents are protected by CRC check sums.
+
+Bad eraseblocks handling
+
+  UBI transparently handles bad eraseblocks. When a physical
+  eraseblock becomes bad, it is substituted by a good physical
+  eraseblock, and the user does not even notice this.
+
+Scrubbing
+
+  On a NAND flash bit flips can occur on any write operation,
+  sometimes also on read. If bit flips persist on the device, at first
+  they can still be corrected by ECC, but once they accumulate,
+  correction will become impossible. Thus it is best to actively scrub
+  the affected eraseblock, by first copying it to a free eraseblock
+  and then erasing the original. The UBI layer performs this type of
+  scrubbing under the covers, transparently to the UBI volume users.
+
+Erase Counts
+
+  UBI maintains an erase count header per eraseblock. This frees
+  higher-level layers (like file systems) from doing this and allows
+  for centralized erase count management instead. The erase counts are
+  used by the wear-levelling algorithm in the UBI layer. The algorithm
+  itself is exchangeable.
+
+Booting from NAND
+
+  For booting directly from NAND flash the hardware must at least be
+  capable of fetching and executing a small portion of the NAND
+  flash. Some NAND flash controllers have this kind of support. They
+  usually limit the window to a few kilobytes in erase block 0. This
+  "initial program loader" (IPL) must then contain sufficient logic to
+  load and execute the next boot phase.
+
+  Due to bad eraseblocks, which may be randomly scattered over the
+  flash device, it is problematic to store the "secondary program
+  loader" (SPL) statically. Also, due to bit-flips it may become
+  corrupted over time. UBI allows to solve this problem gracefully by
+  storing the SPL in a small static UBI volume.
+
+UBI volumes vs. static partitions
+
+  UBI volumes are still very similar to static MTD partitions:
+
+    * both consist of eraseblocks (logical eraseblocks in case of UBI
+      volumes, and physical eraseblocks in case of static partitions;
+    * both support three basic operations - read, write, erase.
+
+  But UBI volumes have the following advantages over traditional
+  static MTD partitions:
+
+    * there are no eraseblock wear-leveling constraints in case of UBI
+      volumes, so the user should not care about this;
+    * there are no bit-flips and bad eraseblocks in case of UBI volumes.
+
+  So, UBI volumes may be considered as flash devices with relaxed
+  restrictions.
+
+Where can it be found?
+
+  Documentation, kernel code and applications can be found in the MTD
+  gits. 
+
+What are the applications for?
+
+  The applications help to create binary flash images for two
+  purposes: pfi files (partial flash images) for in-system update of
+  UBI volumes, and plain binary images, with or without OOB data in
+  case of NAND, for a manufacturing step. Furthermore some tools
+  are/and will be created that allow flash content analysis after a
+  system has crashed.
+
+Who did UBI?
+
+  The original ideas, where UBI is based on, were developed by Andreas
+  Arnez, Frank Haverkamp and Thomas Gleixner. Josh W. Boyer and
+  some others were involved too. The implementation of the kernel
+  layer was done by Artem B. Bityutskiy. The user-space applications
+  and tools were written by Oliver Lohmann with contributions from
+  Frank Haverkamp, Andreas Arnez, and Artem. Joern Engel contributed a
+  patch which modifies JFFS2 so that it can be run on a UBI
+  volume. Thomas Gleixner did modifications to the NAND layer and also
+  some to JFFS2 to make it work.
diff --git a/ubi-utils/old-utils/doc/unubi.roff b/ubi-utils/old-utils/doc/unubi.roff
new file mode 100644
index 0000000..6cebc46
--- /dev/null
+++ b/ubi-utils/old-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/old-utils/inc/libubi.h b/ubi-utils/old-utils/inc/libubi.h
new file mode 100644
index 0000000..82824bd
--- /dev/null
+++ b/ubi-utils/old-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-media.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/old-utils/lib/Makefile.am b/ubi-utils/old-utils/lib/Makefile.am
new file mode 100644
index 0000000..1b0dc01
--- /dev/null
+++ b/ubi-utils/old-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/old-utils/perl/f128_nand_sample.cfg b/ubi-utils/old-utils/perl/f128_nand_sample.cfg
new file mode 100644
index 0000000..e468d9d
--- /dev/null
+++ b/ubi-utils/old-utils/perl/f128_nand_sample.cfg
@@ -0,0 +1,38 @@
+[targets]
+complete=ipl,spl,bootenv,kernel,rootfs
+bootcode=spl,bootenv
+
+# Build sections
+[ipl] 
+image=ipl.bin
+raw_starts=0x00000000
+raw_total_size=128kiB 
+
+[spl]
+image=u-boot.bin
+ubi_ids=2,3
+ubi_size=2MiB
+ubi_type=static
+ubi_names=spl_0,spl_1
+
+[bootenv]
+bootenv_file=bootenv_complete.txt
+ubi_ids=4,5
+ubi_size=128kiB
+ubi_type=static
+ubi_names=bootenv_0,bootenv_1
+
+[kernel]
+image=vmlinux.bin
+ubi_ids=6,7
+ubi_size=6MiB
+ubi_type=static
+ubi_names=kernel_0,kernel_1
+
+[rootfs]
+image=rootfs.bin
+ubi_ids=8,9
+ubi_alignment=2kiB
+ubi_size=16MiB 
+ubi_type=dynamic
+ubi_names=rootfs_0,rootfs_1
diff --git a/ubi-utils/old-utils/perl/f64_nor_sample.cfg b/ubi-utils/old-utils/perl/f64_nor_sample.cfg
new file mode 100644
index 0000000..fd44e27
--- /dev/null
+++ b/ubi-utils/old-utils/perl/f64_nor_sample.cfg
@@ -0,0 +1,39 @@
+[targets]
+complete=ipl,spl,bootenv,kernel,rootfs
+bootcode=spl,bootenv
+rootfs=rootfs
+
+# Build sections
+[ipl] 
+image=ipl.bin
+raw_starts=0x02FE0000, 0x03FE0000
+raw_total_size=128kiB 
+
+[spl]
+image=u-boot.bin
+ubi_ids=2,3
+ubi_size=2MiB
+ubi_type=static
+ubi_names=spl_0,spl_1
+
+[bootenv]
+bootenv_file=bootenv_complete.txt
+ubi_ids=4,5
+ubi_size=128kiB
+ubi_type=static
+ubi_names=bootenv_0,bootenv_1
+
+[kernel]
+image=vmlinux.bin
+ubi_ids=6,7
+ubi_size=6MiB
+ubi_type=static
+ubi_names=kernel_0,kernel_1
+
+[rootfs]
+image=rootfs.bin
+ubi_ids=8,9
+ubi_alignment=2kiB
+ubi_size=16128kiB 
+ubi_type=dynamic
+ubi_names=rootfs_0,rootfs_1
diff --git a/ubi-utils/old-utils/perl/mkpfi b/ubi-utils/old-utils/perl/mkpfi
new file mode 100755
index 0000000..2cce587
--- /dev/null
+++ b/ubi-utils/old-utils/perl/mkpfi
@@ -0,0 +1,723 @@
+#!/usr/bin/perl
+#
+# 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.
+#
+
+#
+# mkpfi
+#
+# This perl program is assembles PFI files from a config file.
+#
+# Author: Oliver Lohmann (oliloh@de.ibm.com)
+#
+use warnings;
+use strict;
+use lib "/usr/lib/perl5"; # Please change this path as you need it, or
+			  # make a proposal how this could be done
+			  # nicer.
+use Getopt::Long;
+use Pod::Usage;
+use Config::IniFiles;
+use File::Temp;
+
+# ----------------------------------------------------------------------------
+# Versions
+our $version : unique = "0.1";
+our $pfi_version : unique = "0x1";
+
+# ----------------------------------------------------------------------------
+# Globals
+my $verbose = 0;
+my $cfg;
+
+my %opts = ();
+my %files = (config => "");
+my @tmp_files;
+
+my %tools = (ubicrc32 => "ubicrc32");
+
+# ----------------------------------------------------------------------------
+# Processing the input sections
+#
+# The idea is to combine each section entry with a function
+# in order to allow some kind of preprocessing for the values
+# before they are written into the PFI file.
+# This is especially useful to be more verbose and
+# user-friendly in the layout file.
+#
+# All key-function hashes are applied after the general
+# validation of the configuration file.
+# If any mandatory key is missing in a section the user
+# will be informed and the PFI creation process is aborted.
+#
+# Default keys will be checked for their presence inside the config
+# file. If they are missing, they will be generated with appr. values.
+
+# Mandatory keys for UBI volumes.
+my %ubi_keys = ("ubi_ids"       => \&check_id_list,
+		"ubi_size"      => \&replace_num,
+		"ubi_type"      => \&replace_type,
+		"ubi_names"     => \&remove_spaces,
+		"ubi_alignment" => \&replace_num);
+
+# Mandatory keys for RAW sections.
+my %raw_keys = ("raw_starts"     => \&expand_starts,
+		"raw_total_size" => \&replace_num);
+
+# Common default keys for documentation and control purposes.
+my %common_keys = ("flags" => \&replace_num,
+		   "label" => \&do_nothing);
+
+# Define any defaults here. Values which maintained in this default
+# region need not to be specified by the user explicitly.
+my %def_ubi_keys      = ("ubi_alignment" => [\&set_default, "0x1"]);
+my %def_raw_keys      = ();
+my %def_common_keys   = ("flags"	 => [\&set_default, "0x0"],
+			 "label"	 => [\&generate_label, ""]);
+
+# ----------------------------------------------------------------------------
+# Input keys, actually the path to the input data.
+
+my %input_keys = ("image" => \&do_nothing);
+
+# Placeholder keys allow the replacement via a special
+# purpose function. E.g. the bootenv_file key will be used
+# to generate bootenv binary data from an text file and
+# replace the bootenv_file key with an image key to handle it
+# in the same way in the further creation process.
+my %input_placeholder_keys = ("bootenv_file" => \&create_bootenv_image);
+
+# ----------------------------------------------------------------------------
+# Helper
+
+# @brief Get current time string.
+sub get_date {
+	my $tmp = scalar localtime;
+	$tmp =~ s/ /_/g;
+	return $tmp;
+}
+
+# @brief Print an info message to stdout.
+sub INFO($) {
+	my $str = shift;
+
+	if (!$verbose) {
+		return;
+	}
+
+	print STDOUT $str;
+}
+
+# @brief Print an error message to stderr.
+sub ERR($) {
+	my $str = shift;
+	print STDERR $str;
+}
+
+# @brief Print a warning message to stderr.
+sub WARN($) {
+	my $str = shift;
+	print STDERR $str;
+}
+
+sub parse_command_line($) {
+	my $opt = shift;
+	my $result = GetOptions( "help"	     => \$$opt{'help'},
+				 "man"	     => \$$opt{'man'},
+				 "config=s"  => \$$opt{'config'},
+				 "verbose"   => \$$opt{'verbose'},
+			       ) or pod2usage(2);
+	pod2usage(1) if defined ($$opt{help});
+	pod2usage(-verbose => 2) if defined ($$opt{man});
+
+	$verbose = $$opt{verbose} if defined $$opt{verbose};
+
+	if (!defined $$opt{config}) {
+		ERR("[ ERROR: No config file specified. Aborting...\n");
+		exit 1;
+	}
+
+}
+
+# @brief Check if all needed tools are in PATH.
+sub check_tools {
+	my $err = 0;
+	my $key;
+
+	foreach $key (keys %tools) {
+		if (`which $tools{$key}` eq "") {
+			ERR("\n") if ($err == 0);
+			ERR("! Please add the tool \'$tools{$key}\' " .
+				"to your path!\n");
+			$err = 1;
+		}
+	}
+	die "[ ERROR: Did not find all needed tools!\n" if $err;
+}
+
+sub open_cfg_file($) {
+	my $fname = shift;
+	my $res = new Config::IniFiles( -file => $fname );
+
+	die "[ ERROR: Cannot load your config file!\n" if (!defined $res);
+	return $res;
+}
+
+sub set_default($$$$) {
+	my ($cfg, $section, $parameter, $def_value) = @_;
+	$cfg->newval($section, $parameter, $def_value);
+	return;
+}
+
+sub generate_label($$$$) {
+	my ($cfg, $section, $parameter, $def_value) = @_;
+	my $new_label = $def_value . $section;
+	$new_label .= "_" . get_date;
+	$cfg->newval($section, $parameter, $new_label);
+	return;
+}
+
+# @brief   Converts any num to a unified hex string, i.e the resulting value
+#	   always starts with "0x" and is aligned to 8 hexdigits.
+# @return  Returns 0 on success, otherwise an error occured.
+#
+sub any_num_to_hex($$) {
+	my $val = shift;
+	my $res = shift;
+
+	# M(iB)
+	if ($val =~ m/([0-9]+)[Mm][i]?[Bb]?/g) {
+		$$res = sprintf("0x%08x", $1 * 1024 * 1024);
+	}
+	# k(iB)
+	elsif ($val =~ m/([0-9]+)[kK][i]?[Bb]?/g) {
+		$$res = sprintf("0x%08x", $1 * 1024);
+	}
+	# hex
+	elsif ($val =~ m/0x?([0-9a-fA-F]+)/g) {
+		$$res = sprintf("0x%08x", hex $1);
+	}
+	# decimal
+	elsif ($val =~ m/^([0-9]+)$/g) {
+		$$res = sprintf("0x%08x", $1);
+	}
+	else {
+		$$res = "";
+		return -1;
+	}
+
+	return 0;
+}
+
+sub remove_spaces($$$) {
+	my ($cfg, $section, $parameter) = @_;
+	my ($start, @starts, @new_starts);
+	my $val = $cfg->val($section, $parameter);
+	my $res;
+
+	$val =~ s/ //g; # spaces
+	$cfg->newval($section, $parameter, $val);
+}
+
+sub expand_starts($$$) {
+	my ($cfg, $section, $parameter) = @_;
+	my ($start, @starts, @new_starts);
+	my $val = $cfg->val($section, $parameter);
+	my $res;
+
+	$val =~ s/ //g; # spaces
+	@starts = split(/,/, $val);
+
+	foreach $start (@starts) {
+		if (any_num_to_hex($start, \$res) != 0) {
+			ERR("[ ERROR: [$section]\n");
+			ERR("[        Expecting a list of numeric " .
+			    "values for parameter: $parameter\n");
+			exit 1;
+		}
+		push (@new_starts, $res);
+	}
+	$res = join(',', @starts);
+
+	$cfg->newval($section, $parameter, $res);
+}
+
+sub check_id_list($$$) {
+	my ($cfg, $section, $parameter) = @_;
+	my $val = $cfg->val($section, $parameter);
+	my $res;
+
+	if (!($val =~ m/^[0-9]+[,0-9]*/)) {
+		ERR("[ ERROR: Syntax error in 'ubi_ids' in " .
+		    "section '$section': $val\n");
+			ERR("[ Aborting... ");
+			exit 1;
+	}
+}
+
+sub replace_type($$$) {
+	my ($cfg, $section, $parameter) = @_;
+	my $val = $cfg->val($section, $parameter);
+	my $res;
+
+	$res = lc($val);
+	grep {$res eq $_} ('static', 'dynamic')
+	    or die "[ ERROR: Unknown UBI Volume Type in " .
+	    "section '$section': $val\n";
+
+	$cfg->newval($section, $parameter, $res);
+}
+
+
+sub replace_num($$$) {
+	my ($cfg, $section, $parameter) = @_;
+	my $val = $cfg->val($section, $parameter);
+	my $res = "";
+
+	if (any_num_to_hex($val, \$res) != 0) {
+		ERR("[ ERROR: [$section]\n");
+		ERR("[        Expecting a numeric value " .
+		    "for parameter: $parameter\n");
+		exit 1;
+	}
+	$cfg->newval($section, $parameter, $res);
+}
+
+sub do_nothing($$$) {
+	my ($cfg, $section, $parameter) = @_;
+	return;
+}
+
+sub bootenv_sanity_check($) {
+	my $env = shift;	# hash array containing bootenv
+	my %pdd = ();
+
+	defined($$env{'pdd'}) or return "'pdd' not defined";
+	foreach (split /,/, $$env{'pdd'}) {
+		defined($$env{$_}) or return "undefined '$_' in pdd";
+		$pdd{$_} = 1;
+	}
+
+	defined $$env{'pdd_preserve'} or
+		return "";
+	foreach (split /,/, $$env{'pdd_preserve'}) {
+		defined($pdd{$_})
+			or return "pdd_preserve field '$_' not in pdd";
+	}
+	return "";
+}
+
+sub create_bootenv_image($$$) {
+	my ($cfg, $section, $parameter) = @_;
+	my $txt_fn = $cfg->val($section, "bootenv_file");
+	my $in;
+
+	my %value = ();
+	my @key = ();
+
+	open $in, "<", $txt_fn
+		or die "[ ERROR: can't open bootenv file '$txt_fn'.\n";
+	while (<$in>) {
+		next if (/^\s*(\#.*)?$/); # Skip comments/whitespace.
+
+		if (/^(\S+?)\+\=(.*)$/) {
+			defined($value{$1}) or
+				die "$txt_fn:$.: error: appending to" .
+					" non-existent '$1'\n";
+			$value{$1} .= $2;
+		} elsif (/^(\S+?)\=(.*)$/) {
+			not defined($value{$1}) or
+				die "$txt_fn:$.: error: trying to" .
+					" redefine '$1'\n";
+			push @key, $1;
+			$value{$1} = $2;
+		} else {
+			die "$txt_fn:$.: error: unrecognized syntax\n";
+		}
+	}
+	close $in;
+
+	$_ = &bootenv_sanity_check(\%value)
+		and die "$txt_fn: error: $_\n";
+
+	my $tmp_file = new File::Temp();
+	push (@tmp_files, $tmp_file);
+
+	foreach (@key) {
+		print $tmp_file "$_=", $value{$_}, "\0";
+	}
+	close $tmp_file;
+
+	$cfg->newval($section, "image", $tmp_file-> filename);
+}
+
+sub process_keys($$$) {
+	my ($cfg, $section, $keys) = @_;
+	my @parameters = $cfg->Parameters($section);
+	my $i;
+
+	for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) {
+		if (defined($$keys{$parameters[$i]})) {
+			$$keys{$parameters[$i]}->($cfg, $section,
+					$parameters[$i]);
+		}
+	}
+
+}
+
+sub is_in_keylist($$) {
+	my ($key, $keys) = @_;
+	my $i;
+
+	for ($i = 0; $i < scalar(@$keys); $i++) {
+		if ($$keys[$i] eq $key) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+sub check_default_keys($$$) {
+	my ($cfg, $section, $keys) = @_;
+	my @parameters = $cfg->Parameters($section);
+	my $key;
+
+	foreach $key (keys %$keys) {
+		if (!is_in_keylist($key, \@parameters)) {
+			$$keys{$key}[0]->
+				($cfg, $section, $key, $$keys{$key}[1]);
+		}
+	}
+
+}
+
+
+
+sub check_keys($$$) {
+	my ($cfg, $section, $keys) = @_;
+	my @parameters = $cfg->Parameters($section);
+	my ($i, $key, $err);
+
+	$err = 0;
+	for ($i = 0 ; $i < scalar(@$keys) ; $i++ ) {
+		if (!is_in_keylist($$keys[$i], \@parameters)) {
+			ERR("[ ERROR: [$section]\n") if $err == 0;
+			$err = 1;
+			ERR("[        Missing key '$$keys[$i]'\n");
+		}
+	}
+
+	if ($err) {
+		ERR("[ Aborting...\n");
+		exit 1;
+	}
+}
+
+sub push_pfi_data($$$$$) {
+	my ($cfg, $section, $pfi_infos, $keys, $mode) = @_;
+	my ($tmp, $i, $hdr);
+
+	my %pfi_info = ();
+	$pfi_info{'mode'} = $mode;
+	$pfi_info{'image'} = $cfg->val($section, "image");
+
+	# Build the PFI header
+	$hdr  = sprintf("PFI!\n");
+	$hdr .= sprintf("version=0x%08x\n", hex $pfi_version);
+	$hdr .= sprintf("mode=$mode\n");
+
+	# calculate the size of the binary data part
+	$tmp = -s $cfg->val($section, "image");
+	if (!defined $tmp) {
+		ERR("[ ERROR: [$section]\n");
+		ERR("[        Missing input image: "
+				. $cfg->val($section, "image") . "\n");
+		exit 1;
+	}
+	# Check for the image to fit into the given space
+	my $quota;
+	if ($mode eq 'raw') {
+		$quota = oct $cfg->val($section, "raw_total_size");
+	} elsif ($mode eq 'ubi') {
+		$quota = oct $cfg->val($section, "ubi_size");
+	}
+	$tmp <= $quota
+		or die "[ERROR: image file too big: " .
+		$cfg->val($section, "image") . "\n";
+	$pfi_info{'size'} = $tmp;
+
+	$hdr .= sprintf("size=0x%08x\n", $tmp);
+
+	my $img_file = $cfg->val($section, "image");
+	my $crc32 = `$tools{'ubicrc32'} $img_file 2>&1`;
+	if (any_num_to_hex($crc32, \$tmp) != 0) {
+		die "[ ERROR: $tools{'ubicrc32'} returned with errors";
+	}
+	$hdr .= sprintf("crc=$tmp\n");
+
+
+	# Process all remaining keys
+	for ($i = 0; $i < scalar (@$keys); $i++) {
+		if ($$keys[$i] eq "image") { # special case image input file
+			if (! -e ($tmp = $cfg->val($section, "image"))) {
+				ERR("[ ERROR: [$section]\n");
+				ERR("[        Cannot find input file $tmp\n");
+				exit 1;
+			}
+			next;
+		}
+		$hdr .= sprintf("%s=%s\n", $$keys[$i],
+				$cfg->val($section, $$keys[$i]));
+	}
+
+	$hdr .= sprintf("\n"); # end marker for PFI-header
+
+	$pfi_info{'header'} = $hdr;
+
+	# store in the header list
+	push @$pfi_infos, \%pfi_info;
+}
+
+sub process_section($$$$$$) {
+	my ($cfg, $section, $pfi_infos, $custom_keys,
+			$def_custom_keys, $mode) = @_;
+	my @keys = (keys %common_keys, keys %$custom_keys);
+	my @complete_keys = (@keys, keys %input_keys);
+
+	# set defaults if necessary
+	check_default_keys($cfg, $section, $def_custom_keys);
+	check_default_keys($cfg, $section, \%def_common_keys);
+
+	# check for placeholders...
+	process_keys($cfg, $section, \%input_placeholder_keys);
+
+	# VALIDATE layout.cfg entries
+	check_keys($cfg, $section, \@complete_keys);
+
+	# execute linked functions (if any)
+	process_keys($cfg, $section, \%common_keys);
+	process_keys($cfg, $section, $custom_keys);
+
+	push_pfi_data($cfg, $section, $pfi_infos, \@keys, $mode);
+}
+
+sub get_section_info($$) {
+	my ($cfg, $section) = @_;
+	my @parameters = $cfg->Parameters($section);
+	my ($ubi, $raw, $i, @res);
+
+	$ubi = $raw = 0;
+	for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) {
+		if ($parameters[$i] =~ m/ubi_/gi) {
+			$ubi = 1;
+			@res = (\%ubi_keys, \%def_ubi_keys, "ubi");
+		}
+		if ($parameters[$i] =~ m/raw_/gi) {
+			$raw = 1;
+			@res = (\%raw_keys, \%def_raw_keys, "raw");
+		}
+	}
+
+	if (($ubi + $raw) != 1)	{ # double definition in section
+		ERR("[ ERROR: Layout error in section '$section'\n");
+		exit 1;
+	}
+
+	return @res;
+}
+
+sub mk_target_list($$) {
+	my $val = shift;
+	my $tmp = shift;
+	my $complete = 0;
+
+	if ($val =~ m/\((.*)\)/g) {
+		$val = $1;
+		$complete = 1;
+	}
+	$val =~ s/ //g; # spaces
+
+	@$tmp = split(/,/, $val);
+
+	return $complete;
+}
+
+sub copy_bytes($$$) {
+	my ($in, $out, $to_copy) = @_;
+
+	while ($to_copy) {
+		my $buf;
+		my $bufsize = 1024*1024;
+
+		$bufsize < $to_copy or $bufsize = $to_copy;
+		read($in, $buf, $bufsize) == $bufsize
+			or die "[ ERROR: Image file shrunk during operation\n";
+		print $out $buf;
+		$to_copy -= $bufsize;
+	}
+}
+
+sub write_target($$) {
+	my ($pfi_infos, $target) = @_;
+	my ($pfi_info);
+
+	INFO("[ Writting target pfi file: '$target.pfi'...\n");
+	if (-e "$target.pfi") {
+		WARN("! Replaced old pfi...\n");
+		`rm -f $target.pfi`;
+	}
+	open(FILE, ">", "$target.pfi")
+		or die "[ ERROR: Cannot create output file: $target.pfi\n";
+	binmode(FILE);
+
+	# @FIXME sort by mode (first raw, then ubi)
+	# Currently this ordering is based on a string comparism. :-)
+	@$pfi_infos = sort {(lc $$a{'mode'}) cmp (lc $$b{'mode'})} @$pfi_infos;
+
+	# Print all headers first
+	foreach $pfi_info (@$pfi_infos) {
+		print FILE $$pfi_info{'header'};
+
+	}
+	# Print the linked data sections
+	print FILE "DATA\n";
+	foreach $pfi_info (@$pfi_infos) {
+		open(IMAGE, "<", $$pfi_info{'image'})
+				or die "[ ERROR: Cannot open input image: " .
+				"$$pfi_info{'image'}" . "\n";
+		binmode(IMAGE);
+		&copy_bytes(\*IMAGE, \*FILE, $$pfi_info{'size'});
+		close(IMAGE) or die "[ ERROR: Cannot close input image: " .
+				"$$pfi_info{'image'}" . "\n";
+	}
+	close(FILE) or die "[ ERROR: Cannot close output file: $target.pfi\n";
+}
+
+sub process_config($) {
+	my $cfg = shift;
+	my @sections = $cfg->Sections;
+	my ($i, $j, $keylist, $def_keylist, $mode, $tmp,
+			@tlist, $complete,@pfi_infos);
+
+	my @parameters = $cfg->Parameters("targets") or
+		die "[ ERROR: Config file has no 'targets' section!\n";
+
+	for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) {
+		INFO("[ Processing target '$parameters[$i]'...\n");
+		@pfi_infos = ();
+
+		# get a list of subtargets
+		$complete = mk_target_list($cfg->val("targets",
+					$parameters[$i]), \@tlist);
+		# build all subtargets
+		for ($j = 0 ; $j < scalar(@tlist) ; $j++ ) {
+			($keylist, $def_keylist, $mode)
+				= get_section_info($cfg, $tlist[$j]);
+			process_section($cfg, $tlist[$j],
+					\@pfi_infos,
+					$keylist, $def_keylist, $mode);
+		}
+
+		write_target(\@pfi_infos, $parameters[$i]);
+	}
+
+	INFO("[ Success.\n");
+
+
+}
+
+sub clear_files() {
+	# @FIXME:
+	# Works implicitly and Fedora seems to have removed
+	# the cleanup call. Thus for now, inactive.
+	# File::Temp::cleanup();
+}
+
+require 5.008_000;		# Tested with version 5.8.0.
+select STDOUT; $| = 1;		# make STDOUT output unbuffered
+select STDERR; $| = 1;		# make STDERR output unbuffered
+
+parse_command_line(\%opts);
+check_tools;
+$cfg = open_cfg_file($opts{config});
+process_config($cfg);
+clear_files;
+
+__END__
+
+
+=head1 NAME
+
+mkpfi - Using GetOpt::Long, Pod::Usage, Config::IniFiles
+
+
+=head1 SYNOPSIS
+
+mkpfi  [OPTIONS ...]
+
+
+	OPTION
+
+	[--config] [--help] [--man]
+
+
+=head1 ABSTRACT
+
+Perl script for generating pdd pfi files from given config files.
+
+=head1 OPTIONS
+
+=over
+
+=item B<--help>
+
+Print out brief help message.
+
+=item B<--usage>
+
+Print usage.
+
+=item B<--config>
+
+Config input file.
+
+=item B<--man>
+
+Print manual page, same as 'perldoc mkpfi'.
+
+=item B<--verbose>
+
+Be verbose!
+
+=back
+
+=head1 BUGS
+
+Report via MTD mailing list
+
+
+=head1 SEE ALSO
+
+http://www.linux-mtd.infradead.org/
+
+
+=head1 AUTHOR
+
+Oliver Lohmann (oliloh@de.ibm.com)
+
+=cut
diff --git a/ubi-utils/old-utils/perl/ubicrc32.pl b/ubi-utils/old-utils/perl/ubicrc32.pl
new file mode 100755
index 0000000..add5f9d
--- /dev/null
+++ b/ubi-utils/old-utils/perl/ubicrc32.pl
@@ -0,0 +1,74 @@
+#!/usr/bin/perl -w
+
+# Subroutine crc32(): Calculates the CRC on a given string.
+
+{
+    my @table = ();
+
+    # @brief Calculate CRC32 for a given string.
+    sub crc32
+    {
+	unless (@table) {
+	    # Initialize the CRC table
+	    my $poly = 0xEDB88320;
+	    @table = ();
+
+	    for my $i (0..255) {
+		my $c = $i;
+
+		for my $j (0..7) {
+		    $c = ($c & 1) ? (($c >> 1) ^ $poly) : ($c >> 1);
+		}
+		$table[$i] = $c;
+	    }
+	}
+	my $s = shift;		# string to calculate the CRC for
+	my $crc = shift;	# CRC start value
+
+	defined($crc)
+	    or $crc = 0xffffffff; # Default CRC start value
+
+	for (my $i = 0; $i < length($s); $i++) {
+	    $crc = $table[($crc ^ ord(substr($s, $i, 1))) & 0xff]
+		^ ($crc >> 8);
+	}
+	return $crc;
+    }
+}
+
+sub crc32_on_file
+{
+    my $file = shift;
+
+    my $crc32 = crc32('');
+    my $buf = '';
+    my $ret = 0;
+
+    while ($ret = read($file, $buf, 8192)) {
+	$crc32 = crc32($buf, $crc32);
+    }
+    defined($ret)
+	or return undef;
+    printf("0x%x\n", $crc32);
+}
+
+
+# Main routine: Calculate the CRCs on the given files and print the
+# results.
+
+{
+    if (@ARGV) {
+	while (my $path = shift) {
+	    my $file;
+	    open $file, "<", $path
+		or die "Error opening '$path'.\n";
+	    
+	    &crc32_on_file($file)
+		or die "Error reading from '$path'.\n";
+	    close $file;
+	}
+    } else {
+	&crc32_on_file(\*STDIN)
+	    or die "Error reading from stdin.\n";
+    }
+}
diff --git a/ubi-utils/old-utils/scripts/Makefile b/ubi-utils/old-utils/scripts/Makefile
new file mode 100644
index 0000000..ebd9bc6
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/Makefile
@@ -0,0 +1,75 @@
+#
+# Makefile
+#
+# Testcase for UBI pfi update.
+#
+# Author:	Frank Haverkamp <haverkam@de.ibm.com>
+#
+
+card		= test
+mkpfi_cfg	= test.cfg
+
+#
+# Some default values you might want to overwrite. Try it if you need
+# it and add more if needed. Note that no real sanity checking is done
+# on those values. If you do it wrong your card has no valid PDD data.
+#
+
+PATH := $(PATH):/opt/ppc/usr/bin:../perl:..
+
+dd		= dd
+sed		= sed
+bin2nand	= bin2nand
+ubigen		= ubigen
+mkpfi		= mkpfi -v
+pfi2bin		= pfi2bin -v
+
+vmlinux_bin	?= test_vmlinux.bin
+rootfs_bin	?= test_rootfs.bin
+spl_bin		?= test_u-boot.bin
+pdd_txt		?= pdd.txt
+
+flashtype	?= nand
+pagesize	?= 2048
+
+compl		?= $(card)_complete
+compl_pfi	?= $(compl).pfi
+compl_img	?= $(compl).img
+
+compl_nand2048_mif=$(compl).$(flashtype)$(pagesize).mif
+compl_nand2048_img=$(compl).$(flashtype)$(pagesize).img
+
+all: $(compl_pfi) $(compl_nand2048_mif)
+
+$(compl_pfi): $(vmlinux_bin) $(rootfs_bin) $(spl_bin)
+	$(mkpfi) -c $(mkpfi_cfg)
+
+# Binary data and out of band data (OOB)
+#
+$(compl_nand2048_mif): $(compl_img)
+	$(bin2nand) -p $(pagesize) -o $(compl_nand2048_mif) $<
+
+# Binary data only
+#
+$(compl_img): $(compl_pfi)
+	$(pfi2bin) -j $(pdd_txt) -o $@ $<
+
+#
+# Default data
+#
+# If the binary data is not available in the current working directory
+# we try to create symlinks to our test data.
+#
+$(vmlinux_bin) $(rootfs_bin) $(spl_bin):
+	@echo
+	@echo "No $@ found, will use defaults !"
+	@echo
+	@echo "OR press CTRL-C to provide your own $@" && 	\
+	sleep 1 &&						\
+	$(dd) if=/dev/urandom of=$@ bs=1M count=1
+
+clean:
+	$(RM) *.pfi *~
+
+distclean: clean
+	$(RM) *.bin *.mif *.oob *.img
diff --git a/ubi-utils/old-utils/scripts/README b/ubi-utils/old-utils/scripts/README
new file mode 100644
index 0000000..899b4a1
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/README
@@ -0,0 +1,11 @@
+README
+======
+
+This procedure creates a test pfi which should be flashed to our
+system with pfiflash. The testcase should read the data back and 
+compare with the original.
+
+We should try not forget to run these tests before we release 
+a new version of UBI.
+
+Frank
diff --git a/ubi-utils/old-utils/scripts/TODO b/ubi-utils/old-utils/scripts/TODO
new file mode 100644
index 0000000..f093e77
--- /dev/null
+++ b/ubi-utils/old-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-utils/scripts/bin2nand2bin_test.sh b/ubi-utils/old-utils/scripts/bin2nand2bin_test.sh
new file mode 100644
index 0000000..a17c91b
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/bin2nand2bin_test.sh
@@ -0,0 +1,184 @@
+#!/bin/sh
+#
+# Testcase for nand2bin and bin2nand. Generate testdata and inject
+# biterrors. Convert data back and compare with original data.
+#
+# Conversion:
+#    bin -> bin2nand -> mif -> nand2bin -> img
+#
+
+inject_biterror=./scripts/inject_biterror.pl
+
+pagesize=2048
+oobsize=64
+
+# Create test data
+dd if=/dev/urandom of=testblock.bin bs=131072 count=1
+
+echo "Test conversion without bitflips ..."
+
+echo -n "Convert bin to mif ... "
+bin2nand --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 --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
+
+echo "Test conversion with uncorrectable ECC erors ..."
+echo -n "Inject biterror at offset $ioffs ... "
+${inject_biterror} --offset=0 --bitmask=0x81 \
+    --input=testblock.mif \
+    --output=testblock_bitflip.mif
+if [ $? -ne "0" ]; then
+    echo "failed!"
+    exit 1
+else
+    echo "ok"
+fi
+
+echo "Convert mif to bin ... "
+rm testblock.img
+nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \
+    testblock_bitflip.mif
+if [ $? -ne "0" ]; then
+    echo "failed!"
+    exit 1
+else
+    echo "ok"
+fi
+
+echo -n "Comparing data, must fail due to uncorrectable ECC ... "
+diff testblock.bin testblock.img
+if [ $? -ne "0" ]; then
+    echo "ok" # Must fail!
+else
+    echo "failed!"
+    exit 1
+fi
+
+echo "Test bitflips in data ... "
+for offs in `seq 0 255` ; do
+
+    cp testblock.mif testblock_bitflip.mif
+
+    for xoffs in 0 256 512 768 ; do
+	let ioffs=$offs+$xoffs
+
+	cp testblock_bitflip.mif testblock_bitflip_tmp.mif
+	echo -n "Inject biterror at offset $ioffs ... "
+	${inject_biterror} --offset=${ioffs} --bitmask=0x01 \
+	    --input=testblock_bitflip_tmp.mif \
+	    --output=testblock_bitflip.mif
+	if [ $? -ne "0" ]; then
+	    echo "failed!"
+	    exit 1
+	else
+	    echo "ok"
+	fi
+    done
+
+    echo "Convert mif to bin ... "
+    rm testblock.img
+    nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \
+	testblock_bitflip.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
+	hexdump testblock.bin > testblock.bin.txt
+	hexdump testblock.img > testblock.img.txt
+	echo "Use tkdiff testblock.bin.txt testblock.img.txt to compare"
+	echo "failed!"
+	exit 1
+    else
+	echo "ok"
+    fi
+
+    # Without correction
+    echo "Convert mif to bin ... "
+    rm testblock.img
+    nand2bin --pagesize=${pagesize} -o testblock.img \
+	testblock_bitflip.mif
+    if [ $? -ne "0" ]; then
+	echo "failed!"
+	exit 1
+    else
+	echo "ok"
+    fi
+
+    echo -n "Comparing data must differ, correction is disabled ... "
+    diff testblock.bin testblock.img
+    if [ $? -ne "0" ]; then
+	echo "ok" # must fail
+    else
+	echo "failed!"
+	exit 1
+    fi
+done
+
+echo "Test bitflips in OOB data ... "
+for offs in `seq 0 $oobsize` ; do
+
+    let ioffs=$pagesize+$offs
+
+    echo -n "Inject biterror at offset $ioffs ... "
+    ${inject_biterror} --offset=${ioffs} --bitmask=0x01 \
+	--input=testblock.mif \
+	--output=testblock_bitflip.mif
+    if [ $? -ne "0" ]; then
+	echo "failed!"
+	exit 1
+    else
+	echo "ok"
+    fi
+
+    echo "Convert mif to bin ... "
+    rm testblock.img
+    nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \
+	testblock_bitflip.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
+	hexdump testblock.bin > testblock.bin.txt
+	hexdump testblock.img > testblock.img.txt
+	echo "Use tkdiff testblock.bin.txt testblock.img.txt to compare"
+	echo "failed!"
+	exit 1
+    else
+	echo "ok"
+    fi
+done
+
diff --git a/ubi-utils/old-utils/scripts/inject_biterror.pl b/ubi-utils/old-utils/scripts/inject_biterror.pl
new file mode 100644
index 0000000..b4a862a
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/inject_biterror.pl
@@ -0,0 +1,94 @@
+#!/usr/bin/perl -w
+#
+# 2007 Frank Haverkamp <haver@vnet.ibm.com>
+#
+# Program for bit-error injection. I am sure that perl experts do it
+# in 1 line. Please let me know how it is done right ;-).
+#
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Pod::Usage;
+
+my $i;
+my $help;
+my $result;
+my $offset = 0;
+my $bitmask = 0x01;
+my $in = "input.mif";
+my $out = "output.mif";
+
+$result = GetOptions ("offset=i"  => \$offset,    # numeric
+		      "bitmask=o" => \$bitmask,   # numeric
+		      "input=s"	  => \$in,	  # string
+		      "output=s"  => \$out,       # string
+		      "help|?"    => \$help) or pod2usage(2);
+
+pod2usage(1) if $help;
+
+my $buf;
+
+open(my $in_fh, "<", $in)
+  or die "Cannot open file $in: $!";
+binmode $in_fh;
+
+open(my $out_fh, ">", $out) or
+  die "Cannot open file $out: $!";
+binmode $out_fh;
+
+$i = 0;
+while (sysread($in_fh, $buf, 1)) {
+
+	$buf = pack('C', unpack('C', $buf) ^ $bitmask) if ($i == $offset);
+	syswrite($out_fh, $buf, 1) or
+	  die "Cannot write to offset $offset: $!";
+	$i++;
+}
+
+close $in_fh;
+close $out_fh;
+
+__END__
+
+=head1 NAME
+
+inject_biterrors.pl
+
+=head1 SYNOPSIS
+
+inject_biterror.pl [options]
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--help>
+
+Print a brief help message and exits.
+
+=item B<--offset>=I<offset>
+
+Byte-offset where bit-error should be injected.
+
+=item B<--bitmask>=I<bitmask>
+
+Bit-mask where to inject errors in the byte.
+
+=item B<--input>=I<input-file>
+
+Input file.
+
+=item B<--output>=I<output-file>
+
+Output file.
+
+=back
+
+=head1 DESCRIPTION
+
+B<inject_biterrors.pl> will read the given input file and inject
+biterrors at the I<offset> specified. The location of the biterrors
+are defined by the I<bitmask> parameter.
+
+=cut
diff --git a/ubi-utils/old-utils/scripts/jffs2_test.sh b/ubi-utils/old-utils/scripts/jffs2_test.sh
new file mode 100755
index 0000000..0cc9f0c
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/jffs2_test.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+#
+# Testcase for JFFS2 verification. We do not want to see any
+# kernel errors occuring when this is executed.
+#
+#
+# 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
+}
+
+echo "***********************************************************************"
+echo "*        jffs2 testing ...                                            *"
+echo "***********************************************************************"
+
+ulimit -c unlimited
+
+for i in `seq 5000`; do
+    echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... "
+    dd if=/dev/urandom of=test.bin bs=$i count=1;
+    if [ $? -ne "0" ] ; then
+        exit_failure
+    fi
+    passed
+
+    echo "Copy to different file ... "
+    dd if=test.bin of=new.bin bs=$i count=1;
+    if [ $? -ne "0" ] ; then
+        exit_failure
+    fi
+    passed
+
+    echo "Comparing files ... "
+    cmp test.bin new.bin
+    dd if=test.bin of=new.bin bs=$i count=1;
+    if [ $? -ne "0" ] ; then
+        exit_failure
+    fi
+    passed
+done
+
+for i in `seq 5000`; do
+    echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... "
+    dd if=/dev/urandom of=foo bs=$i count=1;
+    if [ $? -ne "0" ] ; then
+        exit_failure
+    fi
+    passed
+done
+
+for i in `seq 5000`; do 
+    echo "Testing $i byte (dd if=/dev/zero of=foo bs=$i count=1) ... "
+    dd if=/dev/zero of=foo bs=$i count=1;
+    if [ $? -ne "0" ] ; then
+        exit_failure
+    fi
+    passed
+done
+
+echo "***********************************************************************"
+echo "*               Congratulations, no errors found!                     *"
+echo "*              Have fun with your cool JFFS2 using system!            *"
+echo "***********************************************************************"
+
+exit_success
diff --git a/ubi-utils/old-utils/scripts/mkdevs.pl b/ubi-utils/old-utils/scripts/mkdevs.pl
new file mode 100755
index 0000000..f0fd464
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/mkdevs.pl
@@ -0,0 +1,32 @@
+#!/usr/bin/perl -w
+
+#
+# Author: Artem B. Bityutskiy <dedekind@oktetlabs.ru>
+#
+# A small scrip which creates UBI device nodes in /dev. UBI allocates
+# major number dynamically, so the script looks at /proc/devices to find
+# out UBI's major number.
+#
+
+
+my $proc = '/proc/devices';
+my $regexp = '(\d+) (ubi\d+)$';
+
+
+open FILE, "<", $proc or die "Cannot open $proc file: $!\n";
+my @file = <FILE>;
+close FILE;
+
+foreach (@file) {
+	next if not m/$regexp/g;
+	print "found $2\n";
+
+	system("rm -rf /dev/$2");
+	system("mknod /dev/$2 c $1 0");
+
+	for (my $i = 0; $i < 128; $i += 1) {
+		system("rm -rf /dev/$2_$i");
+		my $j = $i + 1;
+		system("mknod /dev/$2_$i c $1 $j");
+	}
+}
diff --git a/ubi-utils/old-utils/scripts/pdd.txt b/ubi-utils/old-utils/scripts/pdd.txt
new file mode 100644
index 0000000..a3ad915
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/pdd.txt
@@ -0,0 +1,16 @@
+pdd=flash_type,flash_size,flash_eraseblock_size,flash_page_size,card_serialnumber,card_type,ethaddr,eth1addr,eth0,eth1,total,card_hardwarelevel
+pdd_preserve=ethaddr,eth1addr,card_serialnumber
+# To be personalized
+ethaddr=00:04:34:56:78:9A
+eth1addr=00:04:34:56:78:9B
+card_serialnumber=SN0
+# Static for this card type
+total=102M
+card_type=nand_driven_testcard
+card_hardwarelevel=0
+eth0=bcm5222,eth0,0
+eth1=bcm5222,eth0,1
+flash_type=NAND
+flash_size=0x08000000
+flash_eraseblock_size=0x00020000
+flash_page_size=0x00000800
diff --git a/ubi-utils/old-utils/scripts/run_all.sh b/ubi-utils/old-utils/scripts/run_all.sh
new file mode 100755
index 0000000..040bcbd
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/run_all.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+exit_success ()
+{
+	echo "UBI Utils Test Scripts - SUCCESS!"
+	exit 0
+}
+
+exit_failure ()
+{
+	echo $1
+	echo "UBI Utils Test Scripts - FAILED!"
+	exit 1
+}
+
+echo UBI Utils Test Scripts
+
+devno=$1
+logfile=temp-test-log.txt
+
+if test -z "$devno";
+then
+	echo "Usage is $0 <mtd device number>"
+	exit 1
+fi
+
+cwd=`pwd` || exit_failure "pwd failed"
+
+log="${cwd}/${logfile}"
+
+PATH=$PATH:$cwd:..
+
+cat /dev/null > $log || exit_failure "Failed to create $log"
+
+echo "Setting up for jffs2_test.sh" | tee -a $log
+
+avail=`cat /sys/class/ubi/ubi${devno}/avail_eraseblocks`
+size=`cat /sys/class/ubi/ubi${devno}/eraseblock_size`
+
+bytes=`expr $avail \* $size`
+
+ubimkvol -d$devno -s$bytes -n0 -Njtstvol || exit_failure "ubimkvol failed"
+
+mkdir -p /mnt/test_file_system || exit_failure "mkdir failed"
+
+mtd=`cat /proc/mtd | grep jtstvol | cut -d: -f1`
+
+if test -z "$mtd";
+then
+	exit_failure "mtd device not found"
+fi
+
+mount -t jffs2 $mtd /mnt/test_file_system || exit_failure "mount failed"
+
+cd /mnt/test_file_system || exit_failure "cd failed"
+
+echo Running jffs2_test.sh | tee -a $log
+
+jffs2_test.sh >> $log 2>&1 || exit_failure "jffs2_test.sh failed"
+
+rm -f *
+
+cd $cwd || exit_failure "cd failed"
+
+umount /mnt/test_file_system || exit_failure "umount failed"
+
+ubirmvol -d$devno -n0 || exit_failure "ubirmvol failed"
+
+major=`cat /sys/class/ubi/ubi${devno}/dev | cut -d: -f1`
+
+for minor in `seq 0 32`; do
+	if test ! -e /dev/ubi${devno}_$minor ;
+	then
+		mknod /dev/ubi${devno}_$minor c $major $(($minor + 1))
+	fi
+done
+
+rm -f testdata.bin readdata.bin
+
+echo Running ubi_jffs2_test.sh | tee -a $log
+
+ubi_jffs2_test.sh >> $log 2>&1 || exit_failure "ubi_jffs2_test.sh failed"
+
+echo Running ubi_test.sh | tee -a $log
+
+ubi_test.sh >> $log 2>&1 || exit_failure "ubi_test.sh failed"
+
+for minor in `seq 0 32`; do
+	if test -e /sys/class/ubi/ubi${devno}/$minor;
+	then
+		ubirmvol -d$devno -n$minor || exit_failure "ubirmvol failed"
+	fi
+done
+
+echo Running ubi_tools_test.sh | tee -a $log
+
+ubi_tools_test.sh >> $log 2>&1 || exit_failure "ubi_tools_test failed"
+
+rm -f $log
+
+exit_success
diff --git a/ubi-utils/old-utils/scripts/test.cfg b/ubi-utils/old-utils/scripts/test.cfg
new file mode 100644
index 0000000..0b5ec48
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/test.cfg
@@ -0,0 +1,23 @@
+[targets]
+test_complete=spl,kernel,rootfs
+
+[spl]
+image=test_u-boot.bin
+ubi_ids=10,11
+ubi_size=1MiB 
+ubi_type=static
+ubi_names=test_spl_0,test_spl_1
+
+[kernel]
+image=test_vmlinux.bin
+ubi_ids=12,13
+ubi_size=2MiB 
+ubi_type=static
+ubi_names=test_kernel_0,test_kernel_1
+
+[rootfs]
+image=test_rootfs.bin
+ubi_ids=14,15
+ubi_size=2MiB 
+ubi_type=dynamic
+ubi_names=test_rootfs_0,test_rootfs_1
diff --git a/ubi-utils/old-utils/scripts/ubi_jffs2_test.sh b/ubi-utils/old-utils/scripts/ubi_jffs2_test.sh
new file mode 100755
index 0000000..883903d
--- /dev/null
+++ b/ubi-utils/old-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-utils/scripts/ubi_test.sh b/ubi-utils/old-utils/scripts/ubi_test.sh
new file mode 100755
index 0000000..73e4b19
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/ubi_test.sh
@@ -0,0 +1,328 @@
+#!/bin/sh
+#
+# UBI Volume creation/deletion/write/read test script
+#
+# 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 Use ubiupdatevol instead of ubiwritevol
+#
+
+VERSION="1.1"
+
+export PATH=$PATH:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/
+
+UBIMKVOL=ubimkvol
+UBIRMVOL=ubirmvol
+UBIUPDATEVOL=ubiupdatevol
+
+# 128 KiB 131072
+# 256 KiB 262144
+# 512 KiB 524288
+
+SIZE_512K=524288
+SIZE_1M=1310720
+
+SELF=$0
+MINVOL=10
+MAXVOL=12
+
+#
+# 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 -n "*** 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 0 $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
+}
+
+# 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 -n "*** Truncate volume if it exists ... "
+	$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
+    fi
+}
+
+mkvol_rmvol_test ()
+{
+    type=$1
+
+### Test if volume delete on non-existing volumes fails nicely
+
+    for i in `seq $MINVOL $MAXVOL`; do
+	echo "*** Delete if exist or not $i ... "
+
+	delete_volume $i
+	passed
+    done
+
+### Now deleting volumes must fail
+
+    for i in `seq $MINVOL $MAXVOL`; do
+	echo "*** Trying to delete non existing UBI Volume $i ... "
+
+	$UBIRMVOL -d0 -n$i
+	if [ $? -eq "0" ] ; then
+	    exit_failure
+	fi
+	passed
+    done
+
+### Test if volume creation works ok
+
+    for i in `seq $MINVOL $MAXVOL`; do
+	echo "*** Creating UBI Volume $i ... "
+	echo "    $UBIMKVOL -d0 -n$i -t$type -NNEW$i -s $SIZE_512K"
+
+	$UBIMKVOL -d0 -n$i -t$type -N"NEW$i" -s $SIZE_512K
+	if [ $? -ne "0" ] ; then
+	    exit_failure
+	fi
+	passed
+    done
+
+### Now deleting volumes must be ok
+
+    for i in `seq $MINVOL $MAXVOL`; do
+	echo "*** Trying to delete UBI Volume $i ... "
+
+	$UBIRMVOL -d0 -n$i
+	if [ $? -ne "0" ] ; then
+	    exit_failure
+	fi
+	passed
+    done
+
+### Now allocate too large volume
+
+    echo -n "*** Try to create too large volume"
+    $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s 800000000
+    if [ $? -eq "0" ] ; then
+	exit_failure
+    fi
+    passed
+}
+
+# writevol_test - Tests volume creation and writing data to it.
+#
+# @size:    Size of random data to write
+# @type:    Volume type static or dynamic
+#
+writevol_test ()
+{
+    size=$1
+    type=$2
+
+    echo "*** Write volume test with size $size"
+
+### Make sure that volume exist, delete existing volume, create new
+
+    delete_volume $MINVOL
+
+    echo -n "*** Try to create volume ... "
+    $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s $SIZE_1M
+    if [ $? -ne "0" ] ; then
+	exit_failure
+    fi
+    passed
+    
+### Try to create same volume again
+    echo -n "*** Try to create some volume again, this must fail ... "
+    $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s $SIZE_1M
+    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 ... "
+    # sleep 5
+    ls -l testdata.bin
+    echo "    $UBIUPDATEVOL -d0 -n$MINVOL testdata.bin"
+    $UBIUPDATEVOL -d0 -n$MINVOL testdata.bin
+    if [ $? -ne "0" ] ; then
+	exit_failure
+    fi
+    passed
+
+    if [ $type = "static" ] ; then
+	echo "*** Download data with cat ... "
+	cat /dev/ubi0_$MINVOL > readdata.bin
+	if [ $? -ne "0" ] ; then
+	    exit_failure
+	fi
+	passed
+    else
+	echo "*** Download data with dd bs=1 ... "
+	dd if=/dev/ubi0_$MINVOL of=readdata.bin bs=$size count=1
+	if [ $? -ne "0" ] ; then
+	    exit_failure
+	fi
+	passed
+
+	# Size 1 does not work with this test ...
+	#
+	#echo "*** Download data with dd bs=$size ... "
+	#dd if=/dev/ubi0_$MINVOL of=readdata2.bin bs=$size count=1
+	#if [ $? -ne "0" ] ; then
+	#    exit_failure
+	#fi
+	#passed
+
+	#echo -n "*** Comparing data (1) ... "
+	#cmp readdata.bin readdata2.bin
+	#if [ $? -ne "0" ] ; then
+	#    exit_failure
+	#fi
+	#passed
+    fi
+
+    echo -n "*** Comparing data ... "
+    cmp readdata.bin testdata.bin
+    if [ $? -ne "0" ] ; then
+	exit_failure
+    fi
+    passed
+}
+
+echo "***********************************************************************"
+echo "*           UBI Testing starts now ...                                *"
+echo "*                                 Good luck!                          *"
+echo "***********************************************************************"
+
+# 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
+
+echo "***********************************************************************"
+echo "*        mkvol/rmvol testing for static volumes ...                   *"
+echo "***********************************************************************"
+
+mkvol_rmvol_test static
+
+echo "***********************************************************************"
+echo "*        mkvol/rmvol testing for dynamic volumes ...                  *"
+echo "***********************************************************************"
+
+mkvol_rmvol_test dynamic
+
+echo "***********************************************************************"
+echo "*                write to static volumes ...                          *"
+echo "***********************************************************************"
+
+# 10 Erase blocks = (128 KiB - 64 * 2) * 10
+#                 = 1309440 bytes
+# 128 KiB 131072
+# 256 KiB 262144
+# 512 KiB 524288
+
+for size in 262144 131073 131072 2048 1 4096 12800 31313  ; do
+    writevol_test $size static
+done
+
+echo "***********************************************************************"
+echo "*                write to dynamic volumes ...                         *"
+echo "***********************************************************************"
+echo "VERSION: $VERSION"
+
+for size in 131073 131072 2048 1 4096 12800 31313 262144 ; do
+    writevol_test $size dynamic
+done
+
+echo "***********************************************************************"
+echo "*               Congratulations, no errors found!                     *"
+echo "*              Have fun with your cool UBI system!                    *"
+echo "***********************************************************************"
+
+exit_success
diff --git a/ubi-utils/old-utils/scripts/ubi_tools_test.sh b/ubi-utils/old-utils/scripts/ubi_tools_test.sh
new file mode 100755
index 0000000..7f121f1
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/ubi_tools_test.sh
@@ -0,0 +1,252 @@
+#!/bin/sh
+#
+# UBI Volume creation/deletion/write/read test script.
+# Uses our flash update tools and the associated toolchain for flash
+# image creation.
+#
+# 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
+#
+
+VERSION="1.0"
+
+export PATH=$PATH:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/
+
+UBIMKVOL=ubimkvol
+UBIRMVOL=ubirmvol
+UBIWRITEVOL=ubiupdatevol
+PFIFLASH=pfiflash
+CMP=cmp
+
+MAXVOL=32
+
+test_pfi=test_complete.pfi
+real_pfi=example_complete.pfi
+
+# 128 KiB 131072
+# 256 KiB 262144
+# 512 KiB 524288
+
+#
+# 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 -n "*** 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 0 $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
+}
+
+# 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 -n "*** Truncate volume if it exists ... "
+	$UBIWRITEVOL -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
+    fi
+}
+
+echo "***********************************************************************"
+echo "*           UBI Tools Testing starts now ...                          *"
+echo "*                                 Good luck!                          *"
+echo "***********************************************************************"
+
+# 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 other hardware"
+fi
+
+### Test basic stuff
+pfiflash_basic ()
+{
+    echo "Calling pfiflash with test-data ... "
+    echo "    $PFIFLASH $test_pfi"
+    $PFIFLASH $test_pfi
+    if [ $? -ne "0" ]; then
+	echo "Uhhh something went wrong!"
+	exit_failure
+    fi
+    passed
+    
+    echo "Testing if data is correct 10 and 11 ... "
+    $CMP /dev/ubi0_10 /dev/ubi0_11
+    if [ $? -ne "0" ]; then
+	echo "Mirrored volumes not equal!"
+	exit_failure
+    fi
+    passed
+    
+    echo "Comparing against original data ... "
+    $CMP /dev/ubi0_10 test_u-boot.bin
+    if [ $? -ne "0" ]; then
+	echo "Compared volume not equal!"
+	exit_failure
+    fi
+    passed
+    
+    echo "Testing if data is correct 12 and 13 ... "
+    $CMP /dev/ubi0_12 /dev/ubi0_13
+    if [ $? -ne "0" ]; then
+	echo "Mirrored volumes not equal!"
+	exit_failure
+    fi
+    passed
+    
+    echo "Comparing against original data ... "
+    $CMP /dev/ubi0_12 test_vmlinux.bin
+    if [ $? -ne "0" ]; then
+	echo "Compared volume not equal!"
+	exit_failure
+    fi
+    passed
+    
+    echo "Testing if data is correct 14 and 15 ... "
+    $CMP /dev/ubi0_14 /dev/ubi0_15
+    if [ $? -ne "0" ]; then
+	echo "Mirrored volumes not equal!"
+	exit_failure
+    fi
+    passed
+}
+
+### Test each and everything
+pfiflash_advanced ()
+{
+    if [ -e  example_complete.pfi ]; then
+	echo "Calling pfiflash with real data ... "
+	$PFIFLASH -p overwrite --complete example_complete.pfi
+	if [ $? -ne "0" ]; then
+	    echo "Uhhh something went wrong!"
+	    exit_failure
+	fi
+	passed
+	
+	echo "Testing if data is correct 2 and 3 ... "
+	$CMP /dev/ubi0_2 /dev/ubi0_3
+	if [ $? -ne "0" ]; then
+	    echo "Mirrored volumes not equal!"
+	    exit_failure
+	fi
+	passed
+	
+	echo "Comparing against original data ... "
+	$CMP /dev/ubi0_2 u-boot.bin
+	if [ $? -ne "0" ]; then
+	    echo "Compared volume not equal!"
+	    exit_failure
+	fi
+	passed
+	
+	echo "Testing if data is correct 6 and 7 ... "
+	$CMP /dev/ubi0_6 /dev/ubi0_7
+	if [ $? -ne "0" ]; then
+	    echo "Mirrored volumes not equal!"
+	    exit_failure
+	fi
+	passed
+	
+	echo "Comparing against original data ... "
+	$CMP /dev/ubi0_6 vmlinux.bin
+	if [ $? -ne "0" ]; then
+	    echo "Compared volume not equal!"
+	    exit_failure
+	fi
+	passed
+    fi
+}
+
+echo "***********************************************************************"
+echo "*                Testing pfiflash ...                                 *"
+echo "***********************************************************************"
+echo "VERSION: $VERSION"
+
+pfiflash_basic
+pfiflash_advanced
+    
+echo "***********************************************************************"
+echo "*               Congratulations, no errors found!                     *"
+echo "*              Have fun with your cool UBI system!                    *"
+echo "***********************************************************************"
+
+exit_success
diff --git a/ubi-utils/old-utils/scripts/unubi_test.sh b/ubi-utils/old-utils/scripts/unubi_test.sh
new file mode 100644
index 0000000..40dc2e2
--- /dev/null
+++ b/ubi-utils/old-utils/scripts/unubi_test.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+#
+# Use raw NAND data, extract UBI image and apply tool to it.
+# Test basic functionality.
+#
+# 2007 Frank Haverkamp <haver@vnet.ibm.com>
+#
+
+version=1.1
+
+image=data.mif
+oob=oob.bin
+data=data.bin
+pagesize=2048
+volmax=31
+datadir=unubi_data
+
+# general arguments e.g. debug enablement
+# unubi_args="-D"
+
+echo "------------------------------------------------------------------------"
+echo "Testcase: ${0} Version: ${version}"
+echo "------------------------------------------------------------------------"
+echo "Testing nand2bin ..."
+echo "  Input:    ${image}"
+echo "  Data:     ${data}"
+echo "  OOB:      ${oob}"
+echo "  Pagesize: ${pagesize}"
+nand2bin --pagesize ${pagesize} -o ${data} -O ${oob} ${image}
+echo
+
+echo "------------------------------------------------------------------------"
+echo "Testing unubi ..."
+echo "------------------------------------------------------------------------"
+unubi --version
+echo
+
+echo "------------------------------------------------------------------------"
+echo "Trying to extract first ${volmax} volumes ..."
+echo "------------------------------------------------------------------------"
+mkdir -p ${datadir}/volumes
+for v in `seq 0 ${volmax}` ; do
+    unubi ${unubi_args} -r${v} -d${datadir}/volumes ${data}
+    echo -n "."
+done
+echo "ok"
+ls -l ${datadir}/volumes
+echo
+
+echo "------------------------------------------------------------------------"
+echo "Extracting graphics ..."
+echo "------------------------------------------------------------------------"
+unubi -a  -d${datadir} ${data}
+echo "Use gnuplot to display:"
+ls ${datadir}/*.plot
+ls ${datadir}/*.data
+echo
+
+echo "------------------------------------------------------------------------"
+echo "eb-split"
+echo "------------------------------------------------------------------------"
+unubi -e -d${datadir}/eb-split ${data}
+ls -l ${datadir}/eb-split
+echo
+
+echo "------------------------------------------------------------------------"
+echo "vol-split"
+echo "------------------------------------------------------------------------"
+unubi -v -d${datadir}/vol-split ${data}
+ls  -l ${datadir}/vol-split
+echo
+echo "The generated images contain only the data (126KiB in our   "
+echo "case) not including the UBI erase count and volume info     "
+echo "header. For dynamic volumes the data should be the full     "
+echo "126KiB. Unubi cannot know how much of the data is valid.    "
+echo
+
+echo "------------------------------------------------------------------------"
+echo "!vol-split"
+echo "------------------------------------------------------------------------"
+unubi -V -d${datadir}/vol-split! ${data}
+ls -l ${datadir}/vol-split\!
+echo
+echo "The generated images contain the full block data of 128KiB  "
+echo "including the UBI erase count and volume information header."
+echo
+
+echo "------------------------------------------------------------------------"
+echo "Extracting volume info table ..."
+echo "------------------------------------------------------------------------"
+unubi -i -d${datadir} ${data}
+echo "I strongly hope that empty ubi blocks are filled with 0xff! "
+echo
+
+echo "------------------------------------------------------------------------"
+echo "Table 0"
+echo "------------------------------------------------------------------------"
+cat ${datadir}/vol_info_table0
+echo
+
+echo "------------------------------------------------------------------------"
+echo "Table 1"
+echo "------------------------------------------------------------------------"
+cat ${datadir}/vol_info_table1
+echo
diff --git a/ubi-utils/old-utils/src/bin2nand.c b/ubi-utils/old-utils/src/bin2nand.c
new file mode 100644
index 0000000..c7c7ccc
--- /dev/null
+++ b/ubi-utils/old-utils/src/bin2nand.c
@@ -0,0 +1,344 @@
+/*
+ * 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.
+ *
+ * Author: Oliver Lohmann
+ */
+
+/*
+ * Create a flashable NAND image from a binary image
+ *
+ * History:
+ * 1.0 Initial release (tglx)
+ * 1.1 Understands hex and dec input parameters (tglx)
+ * 1.2 Generates separated OOB data, if needed. (oloh)
+ * 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)
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "error.h"
+#include "config.h"
+#include "nandecc.h"
+
+#define PROGRAM_VERSION "1.6"
+
+#define CHECK_ENDP(option, endp) do {			\
+	if (*endp) {					\
+		fprintf(stderr,				\
+			"Parse error option \'%s\'. "	\
+			"No correct numeric value.\n"	\
+			, option);			\
+		exit(EXIT_FAILURE);			\
+	}						\
+} while(0)
+
+typedef enum action_t {
+	ACT_NORMAL	    = 0x00000001,
+} action_t;
+
+#define PAGESIZE	2048
+#define PADDING		   0 /* 0 means, do not adjust anything */
+#define BUFSIZE		4096
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+	"bin2nand - a tool for adding OOB information to a "
+	"binary input file.\n";
+
+static const char *optionsstr =
+"  -c, --copyright          Print copyright informatoin.\n"
+"  -j, --padding=<num>      Padding in Byte/Mi/ki. Default = no padding\n"
+"  -p, --pagesize=<num>     Pagesize in Byte/Mi/ki. Default = 2048\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"
+"      --usage              Give a short usage message\n"
+"  -V, --version            Print program version\n";
+
+static const char *usage =
+"Usage: bin2nand [-c?V] [-j <num>] [-p <num>] [-o <fname>] [-q <fname>]\n"
+"            [--copyright] [--padding=<num>] [--pagesize=<num>]\n"
+"            [--output=<fname>] [--output-oob=<fname>] [--help] [--usage]\n"
+"            [--version]\n";
+
+struct option long_options[] = {
+	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
+	{ .name = "padding", .has_arg = 1, .flag = NULL, .val = 'j' },
+	{ .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 = "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}
+};
+
+static const char copyright [] __attribute__((unused)) =
+	"Copyright IBM Corp. 2006";
+
+typedef struct myargs {
+	action_t action;
+
+	size_t pagesize;
+	size_t padding;
+
+	FILE* fp_in;
+	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)
+{
+	unsigned long long res = strtoull(cp, endp, base);
+
+	switch (**endp) {
+	case 'G':
+		res *= 1024;
+	case 'M':
+		res *= 1024;
+	case 'k':
+	case 'K':
+		res *= 1024;
+	/* "Ki", "ki", "Mi" or "Gi" are to be used. */
+		if ((*endp)[1] == 'i')
+			(*endp) += 2;
+	}
+	return res;
+}
+
+static int
+parse_opt(int argc, char **argv, myargs *args)
+{
+	char* endp;
+
+	while (1) {
+		int key;
+
+		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 '?': /* 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);
+		}
+	}
+
+	if (optind < argc) {
+		args->fp_in = fopen(argv[optind++], "rb");
+		if ((args->fp_in) == NULL) {
+			err_quit("Cannot open file %s for input\n",
+				 argv[optind++]);
+		}
+	}
+
+	return 0;
+}
+
+static int
+process_page(uint8_t* buf, size_t pagesize,
+	FILE *fp_data, FILE* fp_oob, size_t* written)
+{
+	int eccpoi, oobsize;
+	size_t i;
+	uint8_t oobbuf[64];
+
+	memset(oobbuf, 0xff, sizeof(oobbuf));
+
+	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, pagesize, fp_data);
+
+	/* either separate oob or interleave with data */
+	if (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, oobsize, fp_data);
+		if (ferror(fp_data)) {
+			err_msg("IO error\n");
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+int main (int argc, char** argv)
+{
+	int rc = -1;
+	int res = 0;
+	size_t written = 0, read;
+	myargs args = {
+		.action	  = ACT_NORMAL,
+		.pagesize = PAGESIZE,
+		.padding  = PADDING,
+		.fp_in	  = NULL,
+		.file_out_data = NULL,
+		.file_out_oob = NULL,
+	};
+
+	FILE* fp_out_data = stdout;
+	FILE* fp_out_oob = NULL;
+
+	parse_opt(argc, argv, &args);
+
+	uint8_t* buf = calloc(1, BUFSIZE);
+	if (!buf) {
+		err_quit("Cannot allocate page buffer.\n");
+	}
+
+	if (!args.fp_in) {
+		err_msg("No input image specified!\n");
+		goto err;
+	}
+
+	if (args.file_out_data) {
+		fp_out_data = fopen(args.file_out_data, "wb");
+		if (fp_out_data == NULL) {
+			err_sys("Cannot open file %s for output\n",
+					args.file_out_data);
+			goto err;
+		}
+	}
+
+	if (args.file_out_oob) {
+		fp_out_oob = fopen(args.file_out_oob, "wb");
+		if (fp_out_oob == NULL) {
+			err_sys("Cannot open file %s for output\n",
+					args.file_out_oob);
+			goto err;
+		}
+	}
+
+
+	while(1) {
+		read = fread(buf, 1, args.pagesize, args.fp_in);
+		if (feof(args.fp_in) && read == 0)
+			break;
+
+		if (read < args.pagesize) {
+			err_msg("Image not page aligned\n");
+			goto err;
+		}
+
+		if (ferror(args.fp_in)) {
+			err_msg("Read error\n");
+			goto err;
+		}
+
+		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(buf, args.pagesize, fp_out_data,
+				fp_out_oob, &written);
+		if (res != 0)
+			goto err;
+	}
+
+	rc = 0;
+err:
+	free(buf);
+
+	if (args.fp_in)
+		fclose(args.fp_in);
+
+	if (fp_out_oob)
+		fclose(fp_out_oob);
+
+	if (fp_out_data && fp_out_data != stdout)
+		fclose(fp_out_data);
+
+	if (rc != 0) {
+		err_msg("Error during conversion. rc: %d\n", rc);
+		if (args.file_out_data)
+			remove(args.file_out_data);
+		if (args.file_out_oob)
+			remove(args.file_out_oob);
+	}
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/bootenv.c b/ubi-utils/old-utils/src/bootenv.c
new file mode 100644
index 0000000..78198fe
--- /dev/null
+++ b/ubi-utils/old-utils/src/bootenv.c
@@ -0,0 +1,1032 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2008
+ *
+ * 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
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/stat.h>
+#include <bootenv.h>
+
+#include "hashmap.h"
+#include "error.h"
+
+#include <mtd/ubi-media.h>
+#include "crc32.h"
+
+#define ubi_unused __attribute__((unused))
+
+#define BOOTENV_MAXLINE 512 /* max line size of a bootenv.txt file */
+
+/* Structures */
+struct bootenv {
+	hashmap_t map;	 ///< Pointer to hashmap which holds data structure.
+};
+
+struct bootenv_list {
+	hashmap_t head; ///< Pointer to list which holds the data structure.
+};
+
+/**
+ * @brief Remove the '\n' from a given line.
+ * @param line	Input/Output line.
+ * @param size	Size of the line.
+ * @param fp	File Pointer.
+ * @return 0
+ * @return or error
+ */
+static int
+remove_lf(char *line, size_t size, FILE* fp)
+{
+	size_t i;
+
+	for (i = 0; i < size; i++) {
+		if (line[i] == '\n') {
+			line[i] = '\0';
+			return 0;
+		}
+	}
+
+	if (!feof(fp)) {
+		return BOOTENV_EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * @brief Determine if a line contains only WS.
+ * @param line The line to process.
+ * @param size Size of input line.
+ * @return 1	Yes, only WS.
+ * @return 0	No, contains data.
+ */
+static int
+is_ws(const char *line, size_t size)
+{
+	size_t i = 0;
+
+	while (i < size) {
+		switch (line[i]) {
+			case '\n':
+				return 1;
+			case '#':
+				return 1;
+			case ' ':
+				i++;
+				continue;
+			case '\t':
+				i++;
+				continue;
+			default: /* any other char -> no cmnt */
+				return 0;
+		}
+	}
+
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * @brief Build a list from a comma seperated value string.
+ * @param list	Pointer to hashmap structure which shall store
+ *		the list.
+ * @param value	Comma seperated value string.
+ * @return 0
+ * @return or error.
+ */
+static int
+build_list_definition(hashmap_t list, const char *value)
+{
+	int rc = 0;
+	char *str = NULL;
+	char *ptr = NULL;
+	size_t len, i, j;
+
+	/* str: val1,val2 , val4,...,valN     */
+	len = strlen(value);
+	str = (char*) malloc((len+1) * sizeof(char));
+
+	/* 1. reformat string: remove spaces */
+	for (i = 0, j = 0; i < len; i++) {
+		if (value[i] == ' ')
+			continue;
+
+		str[j] = value[i];
+		j++;
+	}
+	str[j] = '\0';
+
+	/* str: val1,val2,val4,...,valN\0*/
+	/* 2. replace ',' seperator with '\0' */
+	len = strlen(str);
+	for (i = 0; i < len; i++) {
+		if (str[i] == ',') {
+			str[i] = '\0';
+		}
+	}
+
+	/* str: val1\0val2\0val4\0...\0valN\0*/
+	/* 3. insert definitions into a hash map, using it like a list */
+	i = j = 0;
+	ptr = str;
+	while (((i = strlen(ptr)) > 0) && (j < len)) {
+		rc = hashmap_add(list, ptr, "");
+		if (rc != 0) {
+			free(str);
+			return rc;
+		}
+		j += i+1;
+		if (j < len)
+			ptr += i+1;
+	}
+
+	free(str);
+	return rc;
+}
+
+/**
+ * @brief Extract a key value pair and add it to a hashmap
+ * @param str	Input string which contains a key value pair.
+ * @param env	The updated handle which contains the new pair.
+ * @return 0
+ * @return or error
+ * @note The input string format is: "key=value"
+ */
+static int
+extract_pair(const char *str, bootenv_t env)
+{
+	int rc = 0;
+	char *key = NULL;
+	char *val = NULL;
+
+	key = strdup(str);
+	if (key == NULL)
+		return -ENOMEM;
+
+	val = strstr(key, "=");
+	if (val == NULL) {
+		rc = BOOTENV_EBADENTRY;
+		goto err;
+	}
+
+	*val = '\0'; /* split strings */
+	val++;
+
+	rc = bootenv_set(env, key, val);
+
+ err:
+	free(key);
+	return rc;
+}
+
+int
+bootenv_destroy(bootenv_t* env)
+{
+	int rc = 0;
+
+	if (env == NULL || *env == NULL)
+		return -EINVAL;
+
+	bootenv_t tmp = *env;
+
+	rc = hashmap_free(tmp->map);
+	if (rc != 0)
+		return rc;
+
+	free(tmp);
+	return rc;
+}
+
+int
+bootenv_create(bootenv_t* env)
+{
+	bootenv_t res;
+	res = (bootenv_t) calloc(1, sizeof(struct bootenv));
+
+	if (res == NULL)
+		return -ENOMEM;
+
+	res->map = hashmap_new();
+
+	if (res->map == NULL) {
+		free(res);
+		return -ENOMEM;
+	}
+
+	*env = res;
+
+	return 0;
+}
+
+
+/**
+ * @brief Read a formatted buffer and scan it for valid bootenv
+ *	  key/value pairs. Add those pairs into a hashmap.
+ * @param env	Hashmap which shall be used to hold the data.
+ * @param buf	Formatted buffer.
+ * @param size	Size of the buffer.
+ * @return 0
+ * @return or error
+ */
+static int
+rd_buffer(bootenv_t env, const char *buf, size_t size)
+{
+	const char *curr = buf;		/* ptr to current key/value pair */
+	uint32_t i, j;			/* current length, chars processed */
+
+	if (buf[size - 1] != '\0')	/* must end in '\0' */
+		return BOOTENV_EFMT;
+
+	for (j = 0; j < size; j += i, curr += i) {
+		/* strlen returns the size of the string upto
+		   but not including the null terminator;
+		   adding 1 to account for '\0' */
+		i = strlen(curr) + 1;
+
+		if (i == 1)
+			return 0;	/* no string found */
+
+		if (extract_pair(curr, env) != 0)
+			return BOOTENV_EINVAL;
+	}
+
+	return 0;
+}
+
+
+int
+bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t* ret_crc)
+{
+	int rc;
+	char *buf = NULL;
+	size_t i = 0;
+	uint32_t crc32_table[256];
+
+	if ((fp == NULL) || (env == NULL))
+		return -EINVAL;
+
+	/* allocate temp buffer */
+	buf = (char*) calloc(1, size * sizeof(char));
+	if (buf == NULL)
+		return -ENOMEM;
+
+	/* FIXME Andreas, please review this I removed size-1 and
+	 * replaced it by just size, I saw the kernel image starting
+	 * with a 0x0060.... and not with the 0x60.... what it should
+	 * be. Is this a tools problem or is it a problem here where
+	 * fp is moved not to the right place due to the former size-1
+	 * here.
+	 */
+	while((i < size) && (!feof(fp))) {
+		int c = fgetc(fp);
+		if (c == EOF) {
+			/* FIXME isn't this dangerous, to update
+			   the boot envs with incomplete data? */
+			buf[i++] = '\0';
+			break;	/* we have enough */
+		}
+		if (ferror(fp)) {
+			rc = -EIO;
+			goto err;
+		}
+
+		buf[i++] = (char)c;
+	}
+
+	/* calculate crc to return */
+	if (ret_crc != NULL) {
+		init_crc32_table(crc32_table);
+		*ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size);
+	}
+
+	/* transfer to hashmap */
+	rc = rd_buffer(env, buf, size);
+
+err:
+	free(buf);
+	return rc;
+}
+
+
+/**
+ * If we have a single file containing the boot-parameter size should
+ * be specified either as the size of the file or as BOOTENV_MAXSIZE.
+ * If the bootparameter are in the middle of a file we need the exact
+ * length of the data.
+ */
+int
+bootenv_read(FILE* fp, bootenv_t env, size_t size)
+{
+	return bootenv_read_crc(fp, env, size, NULL);
+}
+
+
+int
+bootenv_read_txt(FILE* fp, bootenv_t env)
+{
+	int rc = 0;
+	char *buf = NULL;
+	char *line = NULL;
+	char *lstart = NULL;
+	char *curr = NULL;
+	size_t len;
+	size_t size;
+
+	if ((fp == NULL) || (env == NULL))
+		return -EINVAL;
+
+	size = BOOTENV_MAXSIZE;
+
+	/* allocate temp buffers */
+	buf = (char*) calloc(1, size * sizeof(char));
+	lstart = line = (char*) calloc(1, size * sizeof(char));
+	if ((buf == NULL)  || (line == NULL)) {
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	curr = buf;
+	while ((line = fgets(line, size, fp)) != NULL) {
+		if (is_ws(line, size)) {
+			continue;
+		}
+		rc = remove_lf(line, BOOTENV_MAXSIZE, fp);
+		if (rc != 0) {
+			goto err;
+		}
+
+		/* copy new line to binary buffer */
+		len = strlen(line);
+		if (len > size) {
+			rc = -EFBIG;
+			goto err;
+		}
+		size -= len; /* track remaining space */
+
+		memcpy(curr, line, len);
+		curr += len + 1; /* for \0 seperator */
+	}
+
+	rc = rd_buffer(env, buf, BOOTENV_MAXSIZE);
+err:
+	if (buf != NULL)
+		free(buf);
+	if (lstart != NULL)
+		free(lstart);
+	return rc;
+}
+
+static int
+fill_output_buffer(bootenv_t env, char *buf, size_t buf_size_max ubi_unused,
+		size_t *written)
+{
+	int rc = 0;
+	size_t keys_size, i;
+	size_t wr = 0;
+	const char **keys = NULL;
+	const char *val = NULL;
+
+	rc = bootenv_get_key_vector(env, &keys_size, 1, &keys);
+	if (rc != 0)
+		goto err;
+
+	for (i = 0; i < keys_size; i++) {
+		if (wr > BOOTENV_MAXSIZE) {
+			rc = -ENOSPC;
+			goto err;
+		}
+
+		rc = bootenv_get(env, keys[i], &val);
+		if (rc != 0)
+			goto err;
+
+		wr += snprintf(buf + wr, BOOTENV_MAXSIZE - wr,
+				"%s=%s", keys[i], val);
+		wr++; /* for \0 */
+	}
+
+	*written = wr;
+
+err:
+	if (keys != NULL)
+		free(keys);
+
+	return rc;
+}
+
+int
+bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc)
+{
+	int rc = 0;
+	size_t size = 0;
+	char *buf = NULL;
+	uint32_t crc32_table[256];
+
+	if ((fp == NULL) || (env == NULL))
+		return -EINVAL;
+
+	buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char));
+	if (buf == NULL)
+		return -ENOMEM;
+
+
+	rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, &size);
+	if (rc != 0)
+		goto err;
+
+	/* calculate crc to return */
+	if (ret_crc != NULL) {
+		init_crc32_table(crc32_table);
+		*ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size);
+	}
+
+	if (fwrite(buf, size, 1, fp) != 1) {
+		rc = -EIO;
+		goto err;
+	}
+
+err:
+	if (buf != NULL)
+		free(buf);
+	return rc;
+}
+
+int
+bootenv_write(FILE* fp, bootenv_t env)
+{
+	return bootenv_write_crc(fp, env, NULL);
+}
+
+int
+bootenv_compare(bootenv_t first, bootenv_t second)
+{
+	int rc;
+	size_t written_first, written_second;
+	char *buf_first, *buf_second;
+
+	if (first == NULL || second == NULL)
+		return -EINVAL;
+
+	buf_first = malloc(BOOTENV_MAXSIZE);
+	if (!buf_first)
+		return -ENOMEM;
+	buf_second = malloc(BOOTENV_MAXSIZE);
+	if (!buf_second) {
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	rc = fill_output_buffer(first, buf_first, BOOTENV_MAXSIZE,
+			&written_first);
+	if (rc < 0)
+		goto err;
+	rc = fill_output_buffer(second, buf_second, BOOTENV_MAXSIZE,
+			&written_second);
+	if (rc < 0)
+		goto err;
+
+	if (written_first != written_second) {
+		rc = 1;
+		goto err;
+	}
+
+	rc = memcmp(buf_first, buf_second, written_first);
+	if (rc != 0) {
+		rc = 2;
+		goto err;
+	}
+
+err:
+	if (buf_first)
+		free(buf_first);
+	if (buf_second)
+		free(buf_second);
+
+	return rc;
+}
+
+int
+bootenv_size(bootenv_t env, size_t *size)
+{
+	int rc = 0;
+	char *buf = NULL;
+
+	if (env == NULL)
+		return -EINVAL;
+
+	buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char));
+	if (buf == NULL)
+		return -ENOMEM;
+
+	rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, size);
+	if (rc != 0)
+		goto err;
+
+err:
+	if (buf != NULL)
+		free(buf);
+	return rc;
+}
+
+int
+bootenv_write_txt(FILE* fp, bootenv_t env)
+{
+	int rc = 0;
+	size_t size, wr, i;
+	const char **keys = NULL;
+	const char *key = NULL;
+	const char *val = NULL;
+
+	if ((fp == NULL) || (env == NULL))
+		return -EINVAL;
+
+	rc = bootenv_get_key_vector(env, &size, 1, &keys);
+	if (rc != 0)
+		goto err;
+
+	for (i = 0; i < size; i++) {
+		key = keys[i];
+		rc = bootenv_get(env, key, &val);
+		if (rc != 0)
+			goto err;
+
+		wr = fprintf(fp, "%s=%s\n", key, val);
+		if (wr != strlen(key) + strlen(val) + 2) {
+			rc = -EIO;
+			goto err;
+		}
+	}
+
+err:
+	if (keys != NULL)
+		free(keys);
+	return rc;
+}
+
+int
+bootenv_valid(bootenv_t env ubi_unused)
+{
+	/* @FIXME No sanity check implemented. */
+	return 0;
+}
+
+int
+bootenv_copy_bootenv(bootenv_t in, bootenv_t *out)
+{
+	int rc = 0;
+	const char *tmp = NULL;
+	const char **keys = NULL;
+	size_t vec_size, i;
+
+	if ((in == NULL) || (out == NULL))
+		return -EINVAL;
+
+	/* purge output var for sure... */
+	rc = bootenv_destroy(out);
+	if (rc != 0)
+		return rc;
+
+	/* create the new map  */
+	rc = bootenv_create(out);
+	if (rc != 0)
+		goto err;
+
+	/* get the key list from the input map */
+	rc = bootenv_get_key_vector(in, &vec_size, 0, &keys);
+	if (rc != 0)
+		goto err;
+
+	if (vec_size != hashmap_size(in->map)) {
+		rc = BOOTENV_ECOPY;
+		goto err;
+	}
+
+	/* make a deep copy of the hashmap */
+	for (i = 0; i < vec_size; i++) {
+		rc = bootenv_get(in, keys[i], &tmp);
+		if (rc != 0)
+			goto err;
+
+		rc = bootenv_set(*out, keys[i], tmp);
+		if (rc != 0)
+			goto err;
+	}
+
+err:
+	if (keys != NULL)
+		free(keys);
+
+	return rc;
+}
+
+/* ------------------------------------------------------------------------- */
+
+
+int
+bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res,
+		 int *warnings, char *err_buf ubi_unused,
+		 size_t err_buf_size ubi_unused)
+{
+	bootenv_list_t l_old = NULL;
+	bootenv_list_t l_new = NULL;
+	const char *pdd_old = NULL;
+	const char *pdd_new = NULL;
+	const char *tmp = NULL;
+	const char **vec_old = NULL;
+	const char **vec_new = NULL;
+	const char **pdd_up_vec = NULL;
+	size_t vec_old_size, vec_new_size, pdd_up_vec_size, i;
+	int rc = 0;
+
+	if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL))
+		return -EINVAL;
+
+	/* get the pdd strings, e.g.:
+	 * pdd_old=a,b,c
+	 * pdd_new=a,c,d,e */
+	rc = bootenv_get(env_old, "pdd", &pdd_old);
+	if (rc != 0)
+		goto err;
+	rc = bootenv_get(env_new, "pdd", &pdd_new);
+	if (rc != 0)
+		goto err;
+
+	/* put it into a list and then convert it to an vector */
+	rc = bootenv_list_create(&l_old);
+	if (rc != 0)
+		goto err;
+	rc  = bootenv_list_create(&l_new);
+	if (rc != 0)
+		goto err;
+
+	rc = bootenv_list_import(l_old, pdd_old);
+	if (rc != 0)
+		goto err;
+
+	rc = bootenv_list_import(l_new, pdd_new);
+	if (rc != 0)
+		goto err;
+
+	rc = bootenv_list_to_vector(l_old, &vec_old_size, &vec_old);
+	if (rc != 0)
+		goto err;
+
+	rc = bootenv_list_to_vector(l_new, &vec_new_size, &vec_new);
+	if (rc != 0)
+		goto err;
+
+	rc = bootenv_copy_bootenv(env_new, env_res);
+	if (rc != 0)
+		goto err;
+
+	/* calculate the update vector between the old and new pdd */
+	pdd_up_vec = hashmap_get_update_key_vector(vec_old, vec_old_size,
+			vec_new, vec_new_size, &pdd_up_vec_size);
+
+	if (pdd_up_vec == NULL) {
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	if (pdd_up_vec_size != 0) {
+		/* need to warn the user about the unset of
+		 * some pdd/bootenv values */
+		*warnings = BOOTENV_WPDD_STRING_DIFFERS;
+
+		/* remove all entries in the new bootenv load */
+		for (i = 0; i < pdd_up_vec_size; i++) {
+			bootenv_unset(*env_res, pdd_up_vec[i]);
+		}
+	}
+
+	/* generate the keep array and copy old pdd values to new bootenv */
+	for (i = 0; i < vec_old_size; i++) {
+		rc = bootenv_get(env_old, vec_old[i], &tmp);
+		if (rc != 0) {
+			rc = BOOTENV_EPDDINVAL;
+			goto err;
+		}
+		rc = bootenv_set(*env_res, vec_old[i], tmp);
+		if (rc != 0) {
+			goto err;
+		}
+	}
+	/* put the old pdd string into the result map */
+	rc = bootenv_set(*env_res, "pdd", pdd_old);
+	if (rc != 0) {
+		goto err;
+	}
+
+
+err:
+	if (vec_old != NULL)
+		free(vec_old);
+	if (vec_new != NULL)
+		free(vec_new);
+	if (pdd_up_vec != NULL)
+		free(pdd_up_vec);
+
+	bootenv_list_destroy(&l_old);
+	bootenv_list_destroy(&l_new);
+	return rc;
+}
+
+
+int
+bootenv_pdd_overwrite(bootenv_t env_old, bootenv_t env_new,
+		      bootenv_t *env_res, int *warnings ubi_unused,
+		      char *err_buf ubi_unused, size_t err_buf_size ubi_unused)
+{
+	if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL))
+		return -EINVAL;
+
+	return bootenv_copy_bootenv(env_new, env_res);
+}
+
+int
+bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res,
+		  int *warnings ubi_unused, char *err_buf, size_t err_buf_size)
+{
+	if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL))
+		return -EINVAL;
+
+	snprintf(err_buf, err_buf_size, "The PDD merge operation is not "
+			"implemented. Contact: <oliloh@de.ibm.com>");
+
+	return BOOTENV_ENOTIMPL;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int
+bootenv_get(bootenv_t env, const char *key, const char **value)
+{
+	if (env == NULL)
+		return -EINVAL;
+
+	*value = hashmap_lookup(env->map, key);
+	if (*value == NULL)
+		return BOOTENV_ENOTFOUND;
+
+	return 0;
+}
+
+int
+bootenv_get_num(bootenv_t env, const char *key, uint32_t *value)
+{
+	char *endptr = NULL;
+	const char *str;
+
+	if (env == NULL)
+		return 0;
+
+	str = hashmap_lookup(env->map, key);
+	if (!str)
+		return -EINVAL;
+
+	*value = strtoul(str, &endptr, 0);
+
+	if (*endptr == '\0') {
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+int
+bootenv_set(bootenv_t env, const char *key, const char *value)
+{
+	if (env == NULL)
+		return -EINVAL;
+
+	return hashmap_add(env->map, key, value);
+}
+
+int
+bootenv_unset(bootenv_t env, const char *key)
+{
+	if (env == NULL)
+		return -EINVAL;
+
+	return hashmap_remove(env->map, key);
+}
+
+int
+bootenv_get_key_vector(bootenv_t env, size_t* size, int sort,
+		       const char ***vector)
+{
+	if ((env == NULL) || (size == NULL))
+		return -EINVAL;
+
+	*vector = hashmap_get_key_vector(env->map, size, sort);
+
+	if (*vector == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+int
+bootenv_dump(bootenv_t env)
+{
+	if (env == NULL)
+		return -EINVAL;
+
+	return hashmap_dump(env->map);
+}
+
+int
+bootenv_list_create(bootenv_list_t *list)
+{
+	bootenv_list_t res;
+	res = (bootenv_list_t) calloc(1, sizeof(struct bootenv_list));
+
+	if (res == NULL)
+		return -ENOMEM;
+
+	res->head = hashmap_new();
+
+	if (res->head == NULL) {
+		free(res);
+		return -ENOMEM;
+	}
+
+	*list = res;
+	return 0;
+}
+
+int
+bootenv_list_destroy(bootenv_list_t *list)
+{
+	int rc = 0;
+
+	if (list == NULL)
+		return -EINVAL;
+
+	bootenv_list_t tmp = *list;
+	if (tmp == 0)
+		return 0;
+
+	rc = hashmap_free(tmp->head);
+	if (rc != 0)
+		return rc;
+
+	free(tmp);
+	*list = NULL;
+	return 0;
+}
+
+int
+bootenv_list_import(bootenv_list_t list, const char *str)
+{
+	if (list == NULL)
+		return -EINVAL;
+
+	return build_list_definition(list->head, str);
+}
+
+int
+bootenv_list_export(bootenv_list_t list, char **string)
+{
+	size_t size, i, j, bufsize, tmp, rc = 0;
+	const char **items;
+
+	if (list == NULL)
+		return -EINVAL;
+
+	bufsize = BOOTENV_MAXLINE;
+	char *res = (char*) malloc(bufsize * sizeof(char));
+	if (res == NULL)
+		return -ENOMEM;
+
+	rc = bootenv_list_to_vector(list, &size, &items);
+	if (rc != 0) {
+		goto err;
+	}
+
+	j = 0;
+	for (i = 0; i < size; i++) {
+		tmp = strlen(items[i]);
+		if (j >= bufsize) {
+			bufsize += BOOTENV_MAXLINE;
+			res = (char*) realloc(res, bufsize * sizeof(char));
+			if (res == NULL)  {
+				rc = -ENOMEM;
+				goto err;
+			}
+		}
+		memcpy(res + j, items[i], tmp);
+		j += tmp;
+		if (i < (size - 1)) {
+			res[j] = ',';
+			j++;
+		}
+	}
+	j++;
+	res[j] = '\0';
+	free(items);
+	*string = res;
+	return 0;
+err:
+	free(items);
+	return rc;
+}
+
+int
+bootenv_list_add(bootenv_list_t list, const char *item)
+{
+	if ((list == NULL) || (item == NULL))
+		return -EINVAL;
+
+	return hashmap_add(list->head, item, "");
+}
+
+int
+bootenv_list_remove(bootenv_list_t list, const char *item)
+{
+	if ((list == NULL) || (item == NULL))
+		return -EINVAL;
+
+	return hashmap_remove(list->head, item);
+}
+
+int
+bootenv_list_is_in(bootenv_list_t list, const char *item)
+{
+	if ((list == NULL) || (item == NULL))
+		return -EINVAL;
+
+	return hashmap_lookup(list->head, item) != NULL ? 1 : 0;
+}
+
+int
+bootenv_list_to_vector(bootenv_list_t list, size_t *size, const char ***vector)
+{
+	if ((list == NULL) || (size == NULL))
+		return -EINVAL;
+
+	*vector = hashmap_get_key_vector(list->head, size, 1);
+	if (*vector == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int
+bootenv_list_to_num_vector(bootenv_list_t list, size_t *size,
+		uint32_t **vector)
+{
+	int rc = 0;
+	size_t i;
+	uint32_t* res = NULL;
+	char *endptr = NULL;
+	const char **a = NULL;
+
+	rc = bootenv_list_to_vector(list, size, &a);
+	if (rc != 0)
+		goto err;
+
+	res = (uint32_t*) malloc (*size * sizeof(uint32_t));
+	if (!res)
+		goto err;
+
+	for (i = 0; i < *size; i++) {
+		res[i] = strtoul(a[i], &endptr, 0);
+		if (*endptr != '\0')
+			goto err;
+	}
+
+	if (a)
+		free(a);
+	*vector = res;
+	return 0;
+
+err:
+	if (a)
+		free(a);
+	if (res)
+		free(res);
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/bootenv.h b/ubi-utils/old-utils/src/bootenv.h
new file mode 100644
index 0000000..8fecdbf
--- /dev/null
+++ b/ubi-utils/old-utils/src/bootenv.h
@@ -0,0 +1,434 @@
+#ifndef __BOOTENV_H__
+#define __BOOTENV_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.
+ */
+
+#include <stdio.h> /* FILE */
+#include <stdint.h>
+#include <pfiflash.h>
+
+/* DOXYGEN DOCUMENTATION */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file bootenv.h
+ * @author oliloh@de.ibm.com
+ * @version 1.3
+ *
+ * 1.3 Some renaming
+ */
+
+/**
+ * @mainpage Usage
+ *
+ * @section intro Introduction
+ * This library provides all functionality to handle with the so-called
+ * platform description data (PDD) and the bootparameters defined in
+ * U-Boot. It is able to apply the defined PDD operations in PDD update
+ * scenarios. For more information about the PDD and bootparameter
+ * environment "bootenv" confer the PDD documentation.
+ *
+ * @section ret Return codes
+ * This library defines some return codes which will be delivered classified
+ * as warnings or errors. See the "Defines" section for details and numeric
+ * values.
+ *
+ * @section benv Bootenv format description
+ * There are two different input formats:
+ *	- text files
+ *	- binary files
+ *
+ * @subsection txt Text Files
+ * Text files have to be specified like:
+ * @verbatim key1=value1,value2,value7\n key2=value55,value1\n key4=value1\n@endverbatim
+ *
+ * @subsection bin Binary files
+ * Binary files have to be specified like:
+ * @verbatim<CRC32-bit>key1=value1,value2,value7\0key2=value55,value1\0... @endverbatim
+ * You can confer the U-Boot documentation for more details.
+ *
+ * @section benvlists Bootenv lists format description.
+ * Values referenced in the preceeding subsection can be
+ * defined like lists:
+ * @verbatim value1,value2,value3 @endverbatim
+ * There are some situation where a conversion of a comma
+ * seperated list can be useful, e.g. to get a list
+ * of defined PDD entries.
+ */
+
+#define BOOTENV_MAXSIZE (1024 * 100) /* max 100kiB space for bootenv */
+
+/**
+ * @def BOOTENV_ECRC
+ *	@brief Given binary file is to large.
+ * @def BOOTENV_EFMT
+ *	@brief Given bootenv section has an invalid format
+ * @def BOOTENV_EBADENTRY
+ *	@brief Bad entry in the bootenv section.
+ * @def BOOTENV_EINVAL
+ *	@brief Invalid bootenv defintion.
+ * @def BOOTENV_ENOPDD
+ *	@brief Given bootenv sectoin has no PDD defintion string (pdd=...).
+ * @def BOOTENV_EPDDINVAL
+ *	@brief Given bootenv section has an invalid PDD defintion.
+ * @def BOOTENV_ENOTIMPL
+ *	@brief Functionality not implemented.
+ * @def BOOTENV_ECOPY
+ *	@brief Bootenv memory copy error
+ * @def BOOTENV_ENOTFOUND
+ *	@brief Given key has has no value.
+ * @def BOOTENV_EMAX
+ *	@brief Highest error value.
+ */
+#define BOOTENV_ETOOBIG		1
+#define BOOTENV_EFMT		2
+#define BOOTENV_EBADENTRY	3
+#define BOOTENV_EINVAL		4
+#define BOOTENV_ENOPDD		5
+#define BOOTENV_EPDDINVAL	6
+#define BOOTENV_ENOTIMPL	7
+#define BOOTENV_ECOPY		8
+#define BOOTENV_ENOTFOUND	9
+#define BOOTENV_EMAX		10
+
+/**
+ * @def BOOTENV_W
+ *	@brief A warning which is handled internally as an error
+ *	 but can be recovered by manual effort.
+ * @def BOOTENV_WPDD_STRING_DIFFERS
+ *	@brief The PDD strings of old and new PDD differ and
+ *	can cause update problems, because new PDD values
+ *	are removed from the bootenv section completely.
+ */
+#define BOOTENV_W		     20
+#define BOOTENV_WPDD_STRING_DIFFERS  21
+#define BOOTENV_WMAX 22 /* highest warning value */
+
+
+typedef struct bootenv *bootenv_t;
+	/**< A bootenv library handle. */
+
+typedef struct bootenv_list *bootenv_list_t;
+	/**< A handle for a value list. */
+
+typedef int(*pdd_func_t)(bootenv_t, bootenv_t, bootenv_t*,
+		int*, char*, size_t);
+
+
+/**
+ * @brief Get a new handle.
+ * @return 0
+ * @return or error
+ * */
+int bootenv_create(bootenv_t *env);
+
+/**
+ * @brief	Cleanup structure.
+ * @param env	Bootenv structure which shall be destroyed.
+ * @return 0
+ * @return or error
+ */
+int bootenv_destroy(bootenv_t *env);
+
+/**
+ * @brief Copy a bootenv handle.
+ * @param in	The input bootenv.
+ * @param out	The copied output bootenv. Discards old data.
+ * @return 0
+ * @return or error
+ */
+int bootenv_copy_bootenv(bootenv_t in, bootenv_t *out);
+
+/**
+ * @brief Looks for a value inside the bootenv data.
+ * @param env Handle to a bootenv structure.
+ * @param key The key.
+ * @return NULL	 key not found
+ * @return !NULL ptr to value
+ */
+int bootenv_get(bootenv_t env, const char *key, const char **value);
+
+
+/**
+ * @brief Looks for a value inside the bootenv data and converts it to num.
+ * @param env Handle to a bootenv structure.
+ * @param key The key.
+ * @param value A pointer to the resulting numerical value
+ * @return NULL	 key not found
+ * @return !NULL ptr to value
+ */
+int bootenv_get_num(bootenv_t env, const char *key, uint32_t *value);
+
+/**
+ * @brief Set a bootenv value by key.
+ * @param env   Handle to a bootenv structure.
+ * @param key	Key.
+ * @param value	Value to set.
+ * @return 0
+ * @return or error
+ */
+int bootenv_set(bootenv_t env, const char *key, const char *value);
+
+/**
+ * @brief Remove the given key (and its value) from a bootenv structure.
+ * @param env	Handle to a bootenv structure.
+ * @param key	Key.
+ * @return 0
+ * @return or error
+ */
+int bootenv_unset(bootenv_t env, const char *key);
+
+
+/**
+ * @brief Get a vector of all keys which are currently set
+ *        within a bootenv handle.
+ * @param env	Handle to a bootenv structure.
+ * @param size	The size of the allocated array structure.
+ * @param sort	Flag, if set the vector is sorted ascending.
+ * @return NULL on error.
+ * @return !NULL a pointer to the first element the allocated vector.
+ * @warning Free the allocate memory yourself!
+ */
+int bootenv_get_key_vector(bootenv_t env, size_t *size, int sort,
+				const char ***vector);
+
+/**
+ * @brief Calculate the size in bytes which are necessary to write the
+ *        current bootenv section in a *binary file.
+ * @param env	bootenv handle.
+ * @param size  The size in bytes of the bootenv handle.
+ * @return 0
+ * @return or ERROR.
+ */
+int bootenv_size(bootenv_t env, size_t *size);
+
+/**
+ * @brief Read a binary bootenv file.
+ * @param fp	File pointer to input stream.
+ * @param env	bootenv handle.
+ * @param size  maximum data size.
+ * @return 0
+ * @return or ERROR.
+ */
+int bootenv_read(FILE* fp, bootenv_t env, size_t size);
+
+/**
+ * @param ret_crc  return value of crc of read data
+ */
+int bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t *ret_crc);
+
+/**
+ * @brief Read bootenv data from an text/ascii file.
+ * @param fp	File pointer to ascii PDD file.
+ * @param env	bootenv handle
+ * @return 0
+ * @return or ERROR.
+ */
+int bootenv_read_txt(FILE* fp, bootenv_t env);
+
+/**
+ * @brief Write a bootenv structure to the given location (binary).
+ * @param fp	Filepointer to binary file.
+ * @param env	Bootenv structure which shall be written.
+ * @return 0
+ * @return or error
+ */
+int bootenv_write(FILE* fp, bootenv_t env);
+
+/**
+ * @param ret_crc  return value of crc of read data
+ */
+int bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc);
+
+/**
+ * @brief Write a bootenv structure to the given location (text).
+ * @param fp	Filepointer to text file.
+ * @param env	Bootenv structure which shall be written.
+ * @return 0
+ * @return or error
+ */
+int bootenv_write_txt(FILE* fp, bootenv_t env);
+
+/**
+ * @brief Compare bootenvs using memcmp().
+ * @param first	First bootenv.
+ * @param second	Second bootenv.
+ * @return 0 if bootenvs are equal
+ * @return < 0 if error
+ * @return > 0 if unequal
+ */
+int bootenv_compare(bootenv_t first, bootenv_t second);
+
+/**
+ * @brief Prototype for a PDD handling funtion
+ */
+
+/**
+ * @brief The PDD keep operation.
+ * @param env_old The old bootenv structure.
+ * @param env_new The new bootenv structure.
+ * @param env_res The result of PDD keep.
+ * @param warnings A flag which marks any warnings.
+ * @return 0
+ * @return or error
+ * @note For a complete documentation about the algorithm confer the
+ *       PDD documentation.
+ */
+int bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new,
+		bootenv_t *env_res, int *warnings,
+		char *err_buf, size_t err_buf_size);
+
+
+/**
+ * @brief The PDD merge operation.
+ * @param env_old The old bootenv structure.
+ * @param env_new The new bootenv structure.
+ * @param env_res The result of merge-pdd.
+ * @param warnings A flag which marks any warnings.
+ * @return 0
+ * @return or error
+ * @note For a complete documentation about the algorithm confer the
+ *       PDD documentation.
+ */
+int bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new,
+		bootenv_t *env_res, int *warnings,
+		char *err_buf, size_t err_buf_size);
+
+/**
+ * @brief The PDD overwrite operation.
+ * @param env_old The old bootenv structure.
+ * @param env_new The new bootenv structure.
+ * @param env_res The result of overwrite-pdd.
+ * @param warnings A flag which marks any warnings.
+ * @return 0
+ * @return or error
+ * @note For a complete documentation about the algorithm confer the
+ *       PDD documentation.
+ */
+int bootenv_pdd_overwrite(bootenv_t env_new,
+		bootenv_t env_old, bootenv_t *env_res, int *warnings,
+		char *err_buf, size_t err_buf_size);
+
+/**
+ * @brief Dump a bootenv structure to stdout. (Debug)
+ * @param env	Handle to a bootenv structure.
+ * @return 0
+ * @return or error
+ */
+int bootenv_dump(bootenv_t env);
+
+/**
+ * @brief Validate a bootenv structure.
+ * @param env Handle to a bootenv structure.
+ * @return 0
+ * @return or error
+ */
+int bootenv_valid(bootenv_t env);
+
+/**
+ * @brief Create a new bootenv list structure.
+ * @return NULL on error
+ * @return or a new list handle.
+ * @note This structure is used to store values in a list.
+ *       A useful addition when handling PDD strings.
+ */
+int bootenv_list_create(bootenv_list_t *list);
+
+/**
+ * @brief Destroy a bootenv list structure
+ * @param list	Handle to a bootenv list structure.
+ * @return 0
+ * @return or error
+ */
+int bootenv_list_destroy(bootenv_list_t *list);
+
+/**
+ * @brief Import a list from a comma seperated string
+ * @param list	Handle to a bootenv list structure.
+ * @param str		Comma seperated string list.
+ * @return 0
+ * @return or error
+ */
+int bootenv_list_import(bootenv_list_t list, const char *str);
+
+/**
+ * @brief Export a list to a string of comma seperated values.
+ * @param list	Handle to a bootenv list structure.
+ * @return NULL one error
+ * @return or pointer to a newly allocated string.
+ * @warning Free the allocated memory by yourself!
+ */
+int bootenv_list_export(bootenv_list_t list, char **string);
+
+/**
+ * @brief Add an item to the list.
+ * @param list	A handle of a list structure.
+ * @param item	An item.
+ * @return 0
+ * @return or error
+ */
+int bootenv_list_add(bootenv_list_t list, const char *item);
+
+/**
+ * @brief Remove an item from the list.
+ * @param list	A handle of a list structure.
+ * @param item	An item.
+ * @return 0
+ * @return or error
+ */
+int bootenv_list_remove(bootenv_list_t list, const char *item);
+
+/**
+ * @brief Check if a given item is in a given list.
+ * @param list	A handle of a list structure.
+ * @param item	An item.
+ * @return 1 Item is in list.
+ * @return 0 Item is not in list.
+ */
+int bootenv_list_is_in(bootenv_list_t list, const char *item);
+
+
+/**
+ * @brief Convert a list into a vector of all values inside the list.
+ * @param list	Handle to a bootenv structure.
+ * @param size	The size of the allocated vector structure.
+ * @return 0
+ * @return or error
+ * @warning Free the allocate memory yourself!
+ */
+int bootenv_list_to_vector(bootenv_list_t list, size_t *size,
+			   const char ***vector);
+
+/**
+ * @brief Convert a list into a vector of all values inside the list.
+ * @param list	Handle to a bootenv structure.
+ * @param size	The size of the allocated vector structure.
+ * @return 0
+ * @return or error
+ * @warning Free the allocate memory yourself!
+ */
+int bootenv_list_to_num_vector(bootenv_list_t list, size_t *size,
+					uint32_t **vector);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__BOOTENV_H__ */
diff --git a/ubi-utils/old-utils/src/config.h b/ubi-utils/old-utils/src/config.h
new file mode 100644
index 0000000..55e60f3
--- /dev/null
+++ b/ubi-utils/old-utils/src/config.h
@@ -0,0 +1,28 @@
+#ifndef __CONFIG_H__
+#define __CONFIG_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: Frank Haverkamp
+ */
+
+#define PACKAGE_BUGREPORT						\
+	"haver@vnet.ibm.com, dedekind@linutronix.de, or tglx@linutronix.de"
+
+#define ubi_unused __attribute__((unused))
+
+#endif
diff --git a/ubi-utils/old-utils/src/crc32.c b/ubi-utils/old-utils/src/crc32.c
new file mode 100644
index 0000000..666e217
--- /dev/null
+++ b/ubi-utils/old-utils/src/crc32.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Thomas Gleixner
+ */
+
+/*
+ * CRC32 functions
+ *
+ * Can be compiled as seperate object, but is included into the ipl source
+ * so gcc can inline the functions. We optimize for size so the omission of
+ * the function frame is helpful.
+ *
+ */
+
+#include <stdint.h>
+#include <crc32.h>
+
+/* CRC polynomial */
+#define CRC_POLY	0xEDB88320
+
+/**
+ * init_crc32_table - Initialize crc table
+ *
+ * @table:	pointer to the CRC table which must be initialized
+ *
+ * Create CRC32 table for given polynomial. The table is created with
+ * the lowest order term in the highest order bit. So the x^32 term
+ * has to implied in the crc calculation function.
+ */
+void init_crc32_table(uint32_t *table)
+{
+	uint32_t crc;
+	int i, j;
+
+	for (i = 0; i < 256; i++) {
+		crc = i;
+		for (j = 8; j > 0; j--) {
+			if (crc & 1)
+				crc = (crc >> 1) ^ CRC_POLY;
+			else
+				crc >>= 1;
+		}
+		table[i] = crc;
+	}
+}
+
+/**
+ * clc_crc32 - Calculate CRC32 over a buffer
+ *
+ * @table:	pointer to the CRC table
+ * @crc:	initial crc value
+ * @buf:	pointer to the buffer
+ * @len:	number of bytes to calc
+ *
+ * Returns the updated crc value.
+ *
+ * The algorithm resembles a hardware shift register, but calculates 8
+ * bit at once.
+ */
+uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf,
+		   int len)
+{
+	const unsigned char *p = buf;
+
+	while(--len >= 0)
+		crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+	return crc;
+}
diff --git a/ubi-utils/old-utils/src/crc32.h b/ubi-utils/old-utils/src/crc32.h
new file mode 100644
index 0000000..31362b0
--- /dev/null
+++ b/ubi-utils/old-utils/src/crc32.h
@@ -0,0 +1,36 @@
+#ifndef __CRC32_H__
+#define __CRC32_H__
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Author: Thomas Gleixner
+ *
+ * CRC32 functions
+ *
+ * Can be compiled as seperate object, but is included into the ipl source
+ * so gcc can inline the functions. We optimize for size so the omission of
+ * the function frame is helpful.
+ *
+ */
+#include <stdint.h>
+
+void init_crc32_table(uint32_t *table);
+uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len);
+
+#endif /* __CRC32_H__ */
diff --git a/ubi-utils/old-utils/src/eb_chain.c b/ubi-utils/old-utils/src/eb_chain.c
new file mode 100644
index 0000000..da5c2e3
--- /dev/null
+++ b/ubi-utils/old-utils/src/eb_chain.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006, 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Author:  Drake Dowsett, dowsett@de.ibm.com
+ * Contact: Andreas Arnez, arnez@de.ibm.com
+ */
+
+/* see eb_chain.h */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mtd_swab.h>
+#include "unubi_analyze.h"
+#include "crc32.h"
+
+#define COPY(dst, src)							\
+	do {								\
+		dst = malloc(sizeof(*dst));				\
+		if (dst == NULL)					\
+			return -ENOMEM;					\
+		memcpy(dst, src, sizeof(*dst));				\
+	} while (0)
+
+
+/**
+ * inserts an eb_info into the chain starting at head, then searching
+ * linearly for the correct position;
+ * new should contain valid vid and ec headers and the data_crc should
+ * already have been checked before insertion, otherwise the chain
+ * could be have un an undesired manner;
+ * returns -ENOMEM if alloc fails, otherwise SHOULD always return 0,
+ * if not, the code reached the last line and returned -EAGAIN,
+ * meaning there is a bug or a case not being handled here;
+ **/
+int
+eb_chain_insert(struct eb_info **head, struct eb_info *new)
+{
+	uint32_t vol, num, ver;
+	uint32_t new_vol, new_num, new_ver;
+	struct eb_info *prev, *cur, *hist, *ins;
+	struct eb_info **prev_ptr;
+
+	if ((head == NULL) || (new == NULL))
+		return 0;
+
+	if (*head == NULL) {
+		COPY(*head, new);
+		(*head)->next = NULL;
+		return 0;
+	}
+
+	new_vol = be32_to_cpu(new->vid.vol_id);
+	new_num = be32_to_cpu(new->vid.lnum);
+	new_ver = be32_to_cpu(new->vid.leb_ver);
+
+	/** TRAVERSE HORIZONTALY **/
+
+	cur = *head;
+	prev = NULL;
+
+	/* traverse until vol_id/lnum align */
+	vol = be32_to_cpu(cur->vid.vol_id);
+	num = be32_to_cpu(cur->vid.lnum);
+	while ((new_vol > vol) || ((new_vol == vol) && (new_num > num))) {
+		/* insert new at end of chain */
+		if (cur->next == NULL) {
+			COPY(ins, new);
+			ins->next = NULL;
+			cur->next = ins;
+			return 0;
+		}
+
+		prev = cur;
+		cur = cur->next;
+		vol = be32_to_cpu(cur->vid.vol_id);
+		num = be32_to_cpu(cur->vid.lnum);
+	}
+
+	if (prev == NULL)
+		prev_ptr = head;
+	else
+		prev_ptr = &(prev->next);
+
+	/* insert new into the middle of chain */
+	if ((new_vol != vol) || (new_num != num)) {
+		COPY(ins, new);
+		ins->next = cur;
+		*prev_ptr = ins;
+		return 0;
+	}
+
+	/** TRAVERSE VERTICALY **/
+
+	hist = cur;
+	prev = NULL;
+
+	/* traverse until versions align */
+	ver = be32_to_cpu(cur->vid.leb_ver);
+	while (new_ver < ver) {
+		/* insert new at bottom of history */
+		if (hist->older == NULL) {
+			COPY(ins, new);
+			ins->next = NULL;
+			ins->older = NULL;
+			hist->older = ins;
+			return 0;
+		}
+
+		prev = hist;
+		hist = hist->older;
+		ver = be32_to_cpu(hist->vid.leb_ver);
+	}
+
+	if (prev == NULL) {
+		/* replace active version */
+		COPY(ins, new);
+		ins->next = hist->next;
+		*prev_ptr = ins;
+
+		/* place cur in vertical histroy */
+		ins->older = hist;
+		hist->next = NULL;
+		return 0;
+	}
+
+	/* insert between versions, beneath active version */
+	COPY(ins, new);
+	ins->next = NULL;
+	ins->older = prev->older;
+	prev->older = ins;
+	return 0;
+}
+
+
+/**
+ * sets the pointer at pos to the position of the first entry in the chain
+ * with of vol_id and, if given, with the same lnum as *lnum;
+ * if there is no entry in the chain, then *pos is NULL on return;
+ * always returns 0;
+ **/
+int
+eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum,
+		  struct eb_info **pos)
+{
+	uint32_t vol, num;
+	struct eb_info *cur;
+
+	if ((head == NULL) || (*head == NULL) || (pos == NULL))
+		return 0;
+
+	*pos = NULL;
+
+	cur = *head;
+	while (cur != NULL) {
+		vol = be32_to_cpu(cur->vid.vol_id);
+		num = be32_to_cpu(cur->vid.lnum);
+
+		if ((vol_id == vol) && ((lnum == NULL) || (*lnum == num))) {
+			*pos = cur;
+			return 0;
+		}
+
+		cur = cur->next;
+	}
+
+	return 0;
+}
+
+
+/**
+ * prints to stream, the vol_id, lnum and leb_ver for each entry in the
+ * chain, starting at head;
+ * this is intended for debuging purposes;
+ * always returns 0;
+ *
+ * FIXME I do not like the double list traversion ...
+ **/
+int
+eb_chain_print(FILE* stream, struct eb_info *head)
+{
+	struct eb_info *cur;
+
+	if (stream == NULL)
+		stream = stdout;
+
+	if (head == NULL) {
+		fprintf(stream, "EMPTY\n");
+		return 0;
+	}
+	/*               012345678012345678012345678012301230123 0123 01234567 0123457 01234567*/
+	fprintf(stream, "VOL_ID   LNUM     LEB_VER  EC  VID DAT  PBLK PADDR    DSIZE   EC\n");
+	cur = head;
+	while (cur != NULL) {
+		struct eb_info *hist;
+
+		fprintf(stream, "%08x %-8u %08x %-4s%-4s",
+			be32_to_cpu(cur->vid.vol_id),
+			be32_to_cpu(cur->vid.lnum),
+			be32_to_cpu(cur->vid.leb_ver),
+			cur->ec_crc_ok   ? "ok":"bad",
+			cur->vid_crc_ok  ? "ok":"bad");
+		if (cur->vid.vol_type == UBI_VID_STATIC)
+			fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"bad");
+		else	fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"ign");
+		fprintf(stream, " %-4d %08x %-8u %-8llu\n", cur->phys_block,
+			cur->phys_addr, be32_to_cpu(cur->vid.data_size),
+			(unsigned long long)be64_to_cpu(cur->ec.ec));
+
+		hist = cur->older;
+		while (hist != NULL) {
+			fprintf(stream, "%08x %-8u %08x %-4s%-4s",
+				be32_to_cpu(hist->vid.vol_id),
+				be32_to_cpu(hist->vid.lnum),
+				be32_to_cpu(hist->vid.leb_ver),
+				hist->ec_crc_ok   ? "ok":"bad",
+				hist->vid_crc_ok  ? "ok":"bad");
+			if (hist->vid.vol_type == UBI_VID_STATIC)
+				fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"bad");
+			else	fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"ign");
+			fprintf(stream, " %-4d %08x %-8u %-8llu (*)\n",
+				hist->phys_block, hist->phys_addr,
+				be32_to_cpu(hist->vid.data_size),
+				(unsigned long long)be64_to_cpu(hist->ec.ec));
+
+			hist = hist->older;
+		}
+		cur = cur->next;
+	}
+
+	return 0;
+}
+
+
+/**
+ * frees the memory of the entire chain, starting at head;
+ * head will be NULL on return;
+ * always returns 0;
+ **/
+int
+eb_chain_destroy(struct eb_info **head)
+{
+	if (head == NULL)
+		return 0;
+
+	while (*head != NULL) {
+		struct eb_info *cur;
+		struct eb_info *hist;
+
+		cur = *head;
+		*head = (*head)->next;
+
+		hist = cur->older;
+		while (hist != NULL) {
+			struct eb_info *temp;
+
+			temp = hist;
+			hist = hist->older;
+			free(temp);
+		}
+		free(cur);
+	}
+	return 0;
+}
+
diff --git a/ubi-utils/old-utils/src/error.c b/ubi-utils/old-utils/src/error.c
new file mode 100644
index 0000000..4aaedad
--- /dev/null
+++ b/ubi-utils/old-utils/src/error.c
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <string.h>
+#include "error.h"
+
+#define MAXLINE 4096
+#define MAXWIDTH 80
+
+static FILE *logfp = NULL;
+
+static void err_doit(int, int, const char *, va_list);
+
+int
+read_procfile(FILE *fp_out, const char *procfile)
+{
+	FILE *fp;
+
+	if (!fp_out)
+		return -ENXIO;
+
+	fp = fopen(procfile, "r");
+	if (!fp)
+		return -ENOENT;
+
+	while(!feof(fp)) {
+		int c = fgetc(fp);
+
+		if (c == EOF)
+			return 0;
+
+		if (putc(c, fp_out) == EOF)
+			return -EIO;
+
+		if (ferror(fp))
+			return -EIO;
+	}
+	return fclose(fp);
+}
+
+void
+error_initlog(const char *logfile)
+{
+	if (!logfile)
+		return;
+
+	logfp = fopen(logfile, "a+");
+	read_procfile(logfp, "/proc/cpuinfo");
+}
+
+void
+info_msg(const char *fmt, ...)
+{
+	FILE* fpout;
+	char buf[MAXLINE + 1];
+	va_list	ap;
+	int n;
+
+	fpout = stdout;
+
+	va_start(ap, fmt);
+	vsnprintf(buf, MAXLINE, fmt, ap);
+	n = strlen(buf);
+	strcat(buf, "\n");
+
+	fputs(buf, fpout);
+	fflush(fpout);
+	if (fpout != stdout)
+		fclose(fpout);
+
+	va_end(ap);
+	return;
+}
+
+void
+__err_ret(const char *fmt, ...)
+{
+	va_list		ap;
+
+	va_start(ap, fmt);
+	err_doit(1, LOG_INFO, fmt, ap);
+	va_end(ap);
+	return;
+}
+
+void
+__err_sys(const char *fmt, ...)
+{
+	va_list		ap;
+
+	va_start(ap, fmt);
+	err_doit(1, LOG_ERR, fmt, ap);
+	va_end(ap);
+	exit(EXIT_FAILURE);
+}
+
+
+void
+__err_msg(const char *fmt, ...)
+{
+	va_list	ap;
+
+	va_start(ap, fmt);
+	err_doit(0, LOG_INFO, fmt, ap);
+	va_end(ap);
+
+	return;
+}
+
+void
+__err_quit(const char *fmt, ...)
+{
+	va_list		ap;
+
+	va_start(ap, fmt);
+	err_doit(0, LOG_ERR, fmt, ap);
+	va_end(ap);
+	exit(EXIT_FAILURE);
+}
+
+void
+__err_dump(const char *fmt, ...)
+{
+	va_list		ap;
+
+	va_start(ap, fmt);
+	err_doit(1, LOG_ERR, fmt, ap);
+	va_end(ap);
+	abort();		/* dump core and terminate */
+	exit(EXIT_FAILURE);	/* shouldn't get here */
+}
+
+/**
+ * If a logfile is used we must not print on stderr and stdout
+ * anymore. Since pfilfash might be used in a server context, it is
+ * even dangerous to write to those descriptors.
+ */
+static void
+err_doit(int errnoflag, int level __attribute__((unused)),
+	 const char *fmt, va_list ap)
+{
+	FILE* fpout;
+	int errno_save, n;
+	char buf[MAXLINE + 1];
+	fpout = stderr;
+
+	errno_save = errno; /* value caller might want printed */
+
+	vsnprintf(buf, MAXLINE, fmt, ap); /* safe */
+
+	n = strlen(buf);
+
+	if (errnoflag)
+		snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
+	strcat(buf, "\n");
+
+	if (logfp) {
+		fputs(buf, logfp);
+		fflush(logfp);
+		return;		/* exit when logging completes */
+	}
+
+	if (fpout == stderr) {
+		/* perform line wrap when outputting to stderr */
+		int word_len, post_len, chars;
+		char *buf_ptr;
+		const char *frmt = "%*s%n %n";
+
+		chars = 0;
+		buf_ptr = buf;
+		while (sscanf(buf_ptr, frmt, &word_len, &post_len) != EOF) {
+			int i;
+			char word[word_len + 1];
+			char post[post_len + 1];
+
+			strncpy(word, buf_ptr, word_len);
+			word[word_len] = '\0';
+			buf_ptr += word_len;
+			post_len -= word_len;
+
+			if (chars + word_len > MAXWIDTH) {
+				fputc('\n', fpout);
+				chars = 0;
+			}
+			fputs(word, fpout);
+			chars += word_len;
+
+			if (post_len > 0) {
+				strncpy(post, buf_ptr, post_len);
+				post[post_len] = '\0';
+				buf_ptr += post_len;
+			}
+			for (i = 0; i < post_len; i++) {
+				int inc = 1, chars_new;
+
+				if (post[i] == '\t')
+					inc = 8;
+				if (post[i] == '\n') {
+					inc = 0;
+					chars_new = 0;
+				} else
+					chars_new = chars + inc;
+
+				if (chars_new > MAXWIDTH) {
+					fputc('\n', fpout);
+					chars_new = inc;
+				}
+				fputc(post[i], fpout);
+				chars = chars_new;
+			}
+		}
+	}
+	else
+		fputs(buf, fpout);
+	fflush(fpout);
+	if (fpout != stderr)
+		fclose(fpout);
+
+	return;
+}
diff --git a/ubi-utils/old-utils/src/error.h b/ubi-utils/old-utils/src/error.h
new file mode 100644
index 0000000..05d8078
--- /dev/null
+++ b/ubi-utils/old-utils/src/error.h
@@ -0,0 +1,84 @@
+#ifndef __ERROR_H__
+#define __ERROR_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.
+ */
+
+#include <stdio.h>
+
+void error_initlog(const char *logfile);
+int read_procfile(FILE *fp_out, const char *procfile);
+
+void __err_ret(const char *fmt, ...);
+void __err_sys(const char *fmt, ...);
+void __err_msg(const char *fmt, ...);
+void __err_quit(const char *fmt, ...);
+void __err_dump(const char *fmt, ...);
+
+void info_msg(const char *fmt, ...);
+
+#ifdef DEBUG
+#define __loc_msg(str) do {					\
+	__err_msg("[%s. FILE: %s FUNC: %s LINE: %d]\n",		\
+		str, __FILE__, __FUNCTION__, __LINE__);		\
+} while (0)
+#else
+#define __loc_msg(str)
+#endif
+
+
+#define err_dump(fmt, ...) do {					\
+	__loc_msg("ErrDump");					\
+	__err_dump(fmt, ##__VA_ARGS__);				\
+} while (0)
+
+#define err_quit(fmt, ...) do {					\
+	__loc_msg("ErrQuit");					\
+	__err_quit(fmt, ##__VA_ARGS__);				\
+} while (0)
+
+
+#define err_ret(fmt, ...) do {					\
+	__loc_msg("ErrRet");					\
+	__err_ret(fmt, ##__VA_ARGS__);				\
+} while (0)
+
+#define err_sys(fmt, ...) do {					\
+	__loc_msg("ErrSys");					\
+	__err_sys(fmt, ##__VA_ARGS__);				\
+} while (0)
+
+#define err_msg(fmt, ...) do {					\
+	__loc_msg("ErrMsg");					\
+	__err_msg(fmt, ##__VA_ARGS__);				\
+} while (0)
+
+#define log_msg(fmt, ...) do {					\
+		/* __loc_msg("LogMsg");	*/			\
+	__err_msg(fmt, ##__VA_ARGS__);				\
+} while (0)
+
+#ifdef DEBUG
+#define dbg_msg(fmt, ...) do {					\
+	__loc_msg("DbgMsg");					\
+	__err_msg(fmt, ##__VA_ARGS__);				\
+} while (0)
+#else
+#define dbg_msg(fmt, ...) do {} while (0)
+#endif
+
+#endif /* __ERROR_H__ */
diff --git a/ubi-utils/old-utils/src/example_ubi.h b/ubi-utils/old-utils/src/example_ubi.h
new file mode 100644
index 0000000..23c7b54
--- /dev/null
+++ b/ubi-utils/old-utils/src/example_ubi.h
@@ -0,0 +1,28 @@
+#ifndef __EXAMPLE_UBI_H__
+#define __EXAMPLE_UBI_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.
+ */
+
+/**
+ * Defaults for our cards.
+ */
+#define EXAMPLE_UBI_DEVICE	 0
+#define EXAMPLE_BOOTENV_VOL_ID_1 4
+#define EXAMPLE_BOOTENV_VOL_ID_2 5
+
+#endif /* __EXAMPLE_UBI_H__ */
diff --git a/ubi-utils/old-utils/src/hashmap.c b/ubi-utils/old-utils/src/hashmap.c
new file mode 100644
index 0000000..3511d56
--- /dev/null
+++ b/ubi-utils/old-utils/src/hashmap.c
@@ -0,0 +1,412 @@
+/*
+ * 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
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "error.h"
+#include "hashmap.h"
+#define DEFAULT_BUCKETS 4096
+
+#if 0
+#define INFO_MSG(fmt...) do {	\
+	info_msg(fmt);		\
+} while (0)
+#else
+#define INFO_MSG(fmt...)
+#endif
+
+struct hashentry {
+	char* key;	/* key '0' term. str */
+	char* value;    /* payload '0' term. str */
+
+	hashentry_t next;
+};
+
+struct hashmap {
+	size_t entries;     /* current #entries */
+	size_t maxsize;     /* no. of hash buckets */
+	hashentry_t* data;  /* array of buckets */
+};
+
+static int
+is_empty(hashentry_t l)
+{
+	return l == NULL ? 1 : 0;
+}
+
+hashmap_t
+hashmap_new(void)
+{
+	hashmap_t res;
+	res = (hashmap_t) calloc(1, sizeof(struct hashmap));
+
+	if (res == NULL)
+		return NULL;
+
+	res->maxsize = DEFAULT_BUCKETS;
+	res->entries = 0;
+
+	res->data   = (hashentry_t*)
+		calloc(1, res->maxsize * sizeof(struct hashentry));
+
+	if (res->data == NULL)
+		return NULL;
+
+	return res;
+}
+
+static hashentry_t
+new_entry(const char* key, const char* value)
+{
+	hashentry_t res;
+
+	res = (hashentry_t) calloc(1, sizeof(struct hashentry));
+
+	if (res == NULL)
+		return NULL;
+
+	/* allocate key and value and copy them */
+	res->key = strdup(key);
+	if (res->key == NULL) {
+		free(res);
+		return NULL;
+	}
+
+	res->value = strdup(value);
+	if (res->value == NULL) {
+		free(res->key);
+		free(res);
+		return NULL;
+	}
+
+	res->next = NULL;
+
+	return res;
+}
+
+static hashentry_t
+free_entry(hashentry_t e)
+{
+	if (!is_empty(e)) {
+		if(e->key != NULL) {
+			free(e->key);
+		}
+		if(e->value != NULL)
+			free(e->value);
+		free(e);
+	}
+
+	return NULL;
+}
+
+static hashentry_t
+remove_entry(hashentry_t l, const char* key, size_t* entries)
+{
+	hashentry_t lnext;
+	if (is_empty(l))
+		return NULL;
+
+	if(strcmp(l->key,key) == 0) {
+		lnext = l->next;
+		l = free_entry(l);
+		(*entries)--;
+		return lnext;
+	}
+
+	l->next = remove_entry(l->next, key, entries);
+
+	return l;
+}
+
+static hashentry_t
+insert_entry(hashentry_t l, hashentry_t e, size_t* entries)
+{
+	if (is_empty(l)) {
+		(*entries)++;
+		return e;
+	}
+
+	/* check for update */
+	if (strcmp(l->key, e->key) == 0) {
+		e->next = l->next;
+		l = free_entry(l);
+		return e;
+	}
+
+	l->next = insert_entry(l->next, e, entries);
+	return l;
+}
+
+static hashentry_t
+remove_all(hashentry_t l, size_t* entries)
+{
+	hashentry_t lnext;
+	if (is_empty(l))
+		return NULL;
+
+	lnext = l->next;
+	free_entry(l);
+	(*entries)--;
+
+	return remove_all(lnext, entries);
+}
+
+static const char*
+value_lookup(hashentry_t l, const char* key)
+{
+	if (is_empty(l))
+		return NULL;
+
+	if (strcmp(l->key, key) == 0)
+		return l->value;
+
+	return value_lookup(l->next, key);
+}
+
+static void
+print_all(hashentry_t l)
+{
+	if (is_empty(l)) {
+		printf("\n");
+		return;
+	}
+
+	printf("%s=%s", l->key, l->value);
+	if (!is_empty(l->next)) {
+		printf(",");
+	}
+
+	print_all(l->next);
+}
+
+static void
+keys_to_array(hashentry_t l, const char** a, size_t* i)
+{
+	if (is_empty(l))
+		return;
+
+	a[*i] = l->key;
+	(*i)++;
+
+	keys_to_array(l->next, a, i);
+}
+
+uint32_t
+hash_str(const char* str, uint32_t mapsize)
+{
+	uint32_t hash = 0;
+	uint32_t x    = 0;
+	uint32_t i    = 0;
+	size_t   len  = strlen(str);
+
+	for(i = 0; i < len; str++, i++)	{
+		hash = (hash << 4) + (*str);
+		if((x = hash & 0xF0000000L) != 0) {
+			hash ^= (x >> 24);
+			hash &= ~x;
+		}
+	}
+
+	return (hash & 0x7FFFFFFF) % mapsize;
+}
+
+
+int
+hashmap_is_empty(hashmap_t map)
+{
+	if (map == NULL)
+		return -EINVAL;
+
+	return map->entries > 0 ? 1 : 0;
+}
+
+const char*
+hashmap_lookup(hashmap_t map, const char* key)
+{
+	uint32_t i;
+
+	if ((map == NULL) || (key == NULL))
+		return NULL;
+
+	i = hash_str(key, map->maxsize);
+
+	return value_lookup(map->data[i], key);
+}
+
+int
+hashmap_add(hashmap_t map, const char* key, const char* value)
+{
+	uint32_t i;
+	hashentry_t entry;
+
+	if ((map == NULL) || (key == NULL) || (value == NULL))
+		return -EINVAL;
+
+	i = hash_str(key, map->maxsize);
+	entry = new_entry(key, value);
+	if (entry == NULL)
+		return -ENOMEM;
+
+	map->data[i] = insert_entry(map->data[i],
+			entry, &map->entries);
+
+	INFO_MSG("HASH_ADD: chain[%d] key:%s val:%s",i,  key, value);
+	return 0;
+}
+
+int
+hashmap_remove(hashmap_t map, const char* key)
+{
+	uint32_t i;
+
+	if ((map == NULL) || (key == NULL))
+		return -EINVAL;
+
+	i = hash_str(key, map->maxsize);
+	map->data[i] = remove_entry(map->data[i], key, &map->entries);
+
+	return 0;
+}
+
+size_t
+hashmap_size(hashmap_t map)
+{
+	if (map != NULL)
+		return map->entries;
+	else
+		return 0;
+}
+
+int
+hashmap_free(hashmap_t map)
+{
+	size_t i;
+
+	if (map == NULL)
+		return -EINVAL;
+
+	/* "children" first */
+	for(i = 0; i < map->maxsize; i++) {
+		map->data[i] = remove_all(map->data[i], &map->entries);
+	}
+	free(map->data);
+	free(map);
+
+	return 0;
+}
+
+int
+hashmap_dump(hashmap_t map)
+{
+	size_t i;
+	if (map == NULL)
+		return -EINVAL;
+
+	for(i = 0; i < map->maxsize; i++) {
+		if (map->data[i] != NULL) {
+			printf("[%zd]: ", i);
+			print_all(map->data[i]);
+		}
+	}
+
+	return 0;
+}
+
+static const char**
+sort_key_vector(const char** a, size_t size)
+{
+	/* uses bubblesort */
+	size_t i, j;
+	const char* tmp;
+
+	if (size <= 0)
+		return a;
+
+	for (i = size - 1; i > 0; i--) {
+		for (j = 0; j < i; j++) {
+			if (strcmp(a[j], a[j+1]) > 0) {
+				tmp  = a[j];
+				a[j] = a[j+1];
+				a[j+1] = tmp;
+			}
+		}
+	}
+	return a;
+}
+
+const char**
+hashmap_get_key_vector(hashmap_t map, size_t* size, int sort)
+{
+	const char** res;
+	size_t i, j;
+	*size = map->entries;
+
+	res = (const char**) malloc(*size * sizeof(char*));
+	if (res == NULL)
+		return NULL;
+
+	j = 0;
+	for(i=0; i < map->maxsize; i++) {
+		keys_to_array(map->data[i], res, &j);
+	}
+
+	if (sort)
+		res = sort_key_vector(res, *size);
+
+	return res;
+}
+
+int
+hashmap_key_is_in_vector(const char** vec, size_t size, const char* key)
+{
+	size_t i;
+	for (i = 0; i < size; i++) {
+		if (strcmp(vec[i], key) == 0) /* found */
+			return 1;
+	}
+
+	return 0;
+}
+
+const char**
+hashmap_get_update_key_vector(const char** vec1, size_t vec1_size,
+		const char** vec2, size_t vec2_size, size_t* res_size)
+{
+	const char** res;
+	size_t i, j;
+
+	*res_size = vec2_size;
+
+	res = (const char**) malloc(*res_size * sizeof(char*));
+	if (res == NULL)
+		return NULL;
+
+	/* get all keys from vec2 which are not set in vec1 */
+	j = 0;
+	for (i = 0; i < vec2_size; i++) {
+		if (!hashmap_key_is_in_vector(vec1, vec1_size, vec2[i]))
+			res[j++] = vec2[i];
+	}
+
+	*res_size = j;
+	return res;
+}
diff --git a/ubi-utils/old-utils/src/hashmap.h b/ubi-utils/old-utils/src/hashmap.h
new file mode 100644
index 0000000..1b13e95
--- /dev/null
+++ b/ubi-utils/old-utils/src/hashmap.h
@@ -0,0 +1,49 @@
+#ifndef __HASHMAP_H__
+#define __HASHMAP_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: Oliver Lohmann
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct hashentry *hashentry_t;
+typedef struct hashmap *hashmap_t;
+
+hashmap_t hashmap_new(void);
+int hashmap_free(hashmap_t map);
+
+int hashmap_add(hashmap_t map, const char* key, const char* value);
+int hashmap_update(hashmap_t map, const char* key, const char* value);
+int hashmap_remove(hashmap_t map, const char* key);
+const char* hashmap_lookup(hashmap_t map, const char* key);
+
+const char** hashmap_get_key_vector(hashmap_t map, size_t* size, int sort);
+int hashmap_key_is_in_vector(const char** vec, size_t size, const char* key);
+const char** hashmap_get_update_key_vector(const char** vec1, size_t vec1_size,
+		const char** vec2, size_t vec2_size, size_t* res_size);
+
+int hashmap_dump(hashmap_t map);
+
+int hashmap_is_empty(hashmap_t map);
+size_t hashmap_size(hashmap_t map);
+
+uint32_t hash_str(const char* str, uint32_t mapsize);
+
+#endif /* __HASHMAP_H__ */
diff --git a/ubi-utils/old-utils/src/libpfiflash.c b/ubi-utils/old-utils/src/libpfiflash.c
new file mode 100644
index 0000000..b0d454a
--- /dev/null
+++ b/ubi-utils/old-utils/src/libpfiflash.c
@@ -0,0 +1,1325 @@
+/*
+ * Copyright International Business Machines Corp., 2006, 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.
+ */
+
+/*
+ * Authors: Oliver Lohmann <oliloh@de.ibm.com>
+ *	    Drake Dowsett <dowsett@de.ibm.com>
+ * Contact: Andreas Arnez <anrez@de.ibm.com>
+ */
+
+/* TODO Compare data before writing it. This implies that the volume
+ * parameters are compared first: size, alignment, name, type, ...,
+ * this is the same, compare the data. Volume deletion is deffered
+ * until the difference has been found out.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#define __USE_GNU
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/ioctl.h>
+
+#include <libubi.h>
+#include <pfiflash.h>
+
+#include <mtd/ubi-user.h>	/* FIXME Is this ok here? */
+#include <mtd/mtd-user.h>
+
+#include "pfiflash_error.h"
+#include "ubimirror.h"
+#include "error.h"
+#include "reader.h"
+#include "example_ubi.h"
+#include "bootenv.h"
+
+/* ubi-header.h and crc32.h needed for CRC checking */
+#include <mtd/ubi-media.h>	/* FIXME Is this ok here? */
+#include "crc32.h"
+
+#define ubi_unused __attribute__((unused))
+
+#define COMPARE_BUFFER_SIZE 2048
+
+#define DEFAULT_DEV_PATTERN    "/dev/ubi%d"
+#define DEFAULT_VOL_PATTERN    "/dev/ubi%d_%d"
+
+static const char copyright [] ubi_unused =
+	"Copyright International Business Machines Corp., 2006, 2007";
+
+/* simply clear buffer, then write into front of it */
+#define EBUF(fmt...)							\
+		snprintf(err_buf, err_buf_size, fmt);
+
+/* make a history of buffer and then prepend something in front */
+#define EBUF_PREPEND(fmt)						\
+	do {								\
+		int EBUF_HISTORY_LENGTH = strlen(err_buf);		\
+		char EBUF_HISTORY[EBUF_HISTORY_LENGTH + 1];		\
+		strncpy(EBUF_HISTORY, err_buf, EBUF_HISTORY_LENGTH + 1);\
+		EBUF(fmt ": %s", EBUF_HISTORY);				\
+	} while (0)
+
+/* An array of PDD function pointers indexed by the algorithm. */
+static pdd_func_t pdd_funcs[PDD_HANDLING_NUM]  =
+	{
+		&bootenv_pdd_keep,
+		&bootenv_pdd_merge,
+		&bootenv_pdd_overwrite
+	};
+
+typedef enum ubi_update_process_t {
+	UBI_REMOVE = 0,
+	UBI_WRITE,
+	UBI_COMPARE,
+} ubi_update_process_t;
+
+
+/**
+ * skip_raw_volumes - reads data from pfi to advance fp past raw block
+ * @pfi:	fp to pfi data
+ * @pfi_raws:	header information
+ *
+ * Error handling):
+ *	when early EOF in pfi data
+ *	- returns -PFIFLASH_ERR_EOF, err_buf matches text to err
+ *	when file I/O error
+ *	- returns -PFIFLASH_ERR_FIO, err_buf matches text to err
+ **/
+static int
+skip_raw_volumes(FILE* pfi, list_t pfi_raws,
+		  char* err_buf, size_t err_buf_size)
+{
+	int rc;
+	void *i;
+	list_t ptr;
+
+	if (is_empty(pfi_raws))
+		return 0;
+
+	rc = 0;
+	foreach(i, ptr, pfi_raws) {
+		size_t j;
+		pfi_raw_t raw;
+
+		raw = (pfi_raw_t)i;
+		for(j = 0; j < raw->data_size; j++) {
+			int c;
+
+			c = fgetc(pfi);
+			if (c == EOF)
+				rc = -PFIFLASH_ERR_EOF;
+			else if (ferror(pfi))
+				rc = -PFIFLASH_ERR_FIO;
+
+			if (rc != 0)
+				goto err;
+		}
+	}
+
+ err:
+	EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+	return rc;
+}
+
+
+/**
+ * my_ubi_mkvol - wraps the ubi_mkvol functions and impl. bootenv update hook
+ * @devno:	UBI device number.
+ * @s:		Current seqnum.
+ * @u:		Information about the UBI volume from the PFI.
+ *
+ * Error handling:
+ *	when UBI system couldn't be opened
+ *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
+ *	when UBI system couldn't create a volume
+ *	- returns -PFIFLASH_ERR_UBI_MKVOL, err_buf matches text to err
+ **/
+static int
+my_ubi_mkvol(int devno, int s, pfi_ubi_t u,
+	     char *err_buf, size_t err_buf_size)
+{
+	int rc, type;
+	char path[PATH_MAX];
+	libubi_t ulib;
+	struct ubi_mkvol_request req;
+
+	rc = 0;
+	ulib = NULL;
+
+	log_msg("[ ubimkvol id=%d, size=%d, data_size=%d, type=%d, "
+		"alig=%d, nlen=%d, name=%s",
+		u->ids[s], u->size, u->data_size, u->type, u->alignment,
+		strnlen(u->names[s], PFI_UBI_VOL_NAME_LEN), u->names[s]);
+
+	ulib = libubi_open();
+	if (ulib == NULL) {
+		rc = -PFIFLASH_ERR_UBI_OPEN;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	}
+
+	switch (u->type) {
+	case pfi_ubi_static:
+		type = UBI_STATIC_VOLUME; break;
+	case pfi_ubi_dynamic:
+	default:
+		type = UBI_DYNAMIC_VOLUME;
+	}
+
+	snprintf(path, PATH_MAX, DEFAULT_DEV_PATTERN, devno);
+
+	req.vol_id = u->ids[s];
+	req.alignment = u->alignment;
+	req.bytes = u->size;
+	req.vol_type = type;
+	req.name = u->names[s];
+
+	rc = ubi_mkvol(ulib, path, &req);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_UBI_MKVOL;
+		EBUF(PFIFLASH_ERRSTR[-rc], u->ids[s]);
+		goto err;
+	}
+
+ err:
+	if (ulib != NULL)
+		libubi_close(ulib);
+
+	return rc;
+}
+
+
+/**
+ * my_ubi_rmvol - a wrapper around the UBI library function ubi_rmvol
+ * @devno	UBI device number
+ * @id		UBI volume id to remove
+ *
+ * If the volume does not exist, the function will return success.
+ *
+ * Error handling:
+ *	when UBI system couldn't be opened
+ *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
+ *	when UBI system couldn't update (truncate) a volume
+ *	- returns -PFIFLASH_ERR_UBI_VOL_UPDATE, err_buf matches text to err
+ *	when UBI system couldn't remove a volume
+ *	- returns -PFIFLASH_ERR_UBI_RMVOL, err_buf matches text to err
+ **/
+static int
+my_ubi_rmvol(int devno, uint32_t id,
+	     char *err_buf, size_t err_buf_size)
+{
+	int rc, fd;
+	char path[PATH_MAX];
+	libubi_t ulib;
+
+	rc = 0;
+	ulib = NULL;
+
+	log_msg("[ ubirmvol id=%d", id);
+
+	ulib = libubi_open();
+	if (ulib == NULL) {
+		rc = -PFIFLASH_ERR_UBI_OPEN;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	}
+
+	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
+
+	/* truncate whether it exist or not */
+	fd = open(path, O_RDWR);
+	if (fd < 0) {
+		libubi_close(ulib);
+		return 0;	/* not existent, return 0 */
+	}
+
+	rc = ubi_update_start(ulib, fd, 0);
+	close(fd);
+	if (rc < 0) {
+		rc = -PFIFLASH_ERR_UBI_VOL_UPDATE;
+		EBUF(PFIFLASH_ERRSTR[-rc], id);
+		goto err;	/* if EBUSY than empty device, continue */
+	}
+
+	snprintf(path, PATH_MAX, DEFAULT_DEV_PATTERN, devno);
+
+	rc = ubi_rmvol(ulib, path, id);
+	if (rc != 0) {
+#ifdef DEBUG
+		int rc_old = rc;
+		dbg_msg("Remove UBI volume %d returned with error: %d "
+			"errno=%d", id, rc_old, errno);
+#endif
+
+		rc = -PFIFLASH_ERR_UBI_RMVOL;
+		EBUF(PFIFLASH_ERRSTR[-rc], id);
+
+		/* TODO Define a ubi_rmvol return value which says
+		 * sth like EUBI_NOSUCHDEV. In this case, a failed
+		 * operation is acceptable. Everything else has to be
+		 * classified as real error. But talk to Andreas Arnez
+		 * before defining something odd...
+		 */
+		/* if ((errno == EINVAL) || (errno == ENODEV))
+		   return 0; */ /* currently it is EINVAL or ENODEV */
+
+		goto err;
+	}
+
+ err:
+	if (ulib != NULL)
+		libubi_close(ulib);
+
+	return rc;
+}
+
+
+/**
+ * read_bootenv_volume - reads the current bootenv data from id into be_old
+ * @devno	UBI device number
+ * @id		UBI volume id to remove
+ * @bootenv_old	to hold old boot_env data
+ *
+ * Error handling:
+ *	when UBI system couldn't be opened
+ *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
+ *	when UBI system couldn't open a volume to read
+ *	- returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err
+ *	when couldn't read bootenv data
+ *	- returns -PFIFLASH_ERR_BOOTENV_READ, err_buf matches text to err
+ **/
+static int
+read_bootenv_volume(int devno, uint32_t id, bootenv_t bootenv_old,
+		    char *err_buf, size_t err_buf_size)
+{
+	int rc;
+	FILE* fp_in;
+	char path[PATH_MAX];
+	libubi_t ulib;
+
+	rc = 0;
+	fp_in = NULL;
+	ulib = NULL;
+
+	ulib = libubi_open();
+	if (ulib == NULL) {
+		rc = -PFIFLASH_ERR_UBI_OPEN;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	}
+
+	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
+
+	fp_in = fopen(path, "r");
+	if (!fp_in) {
+		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
+		EBUF(PFIFLASH_ERRSTR[-rc], id);
+		goto err;
+	}
+
+	log_msg("[ reading old bootenvs ...");
+
+	/* Save old bootenvs for reference */
+	rc = bootenv_read(fp_in, bootenv_old, BOOTENV_MAXSIZE);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_READ;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	}
+
+ err:
+	if (fp_in)
+		fclose(fp_in);
+	if (ulib)
+		libubi_close(ulib);
+
+	return rc;
+}
+
+
+/**
+ * write_bootenv_volume - writes data from PFI file int to bootenv UBI volume
+ * @devno	UBI device number
+ * @id		UBI volume id
+ * @bootend_old	old PDD data from machine
+ * @pdd_f	function to handle PDD with
+ * @fp_in	new pdd data contained in PFI
+ * @fp_in_size	data size of new pdd data in PFI
+ * @pfi_crc	crc value from PFI header
+ *
+ * Error handling:
+ *	when UBI system couldn't be opened
+ *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
+ *	when bootenv can't be created
+ *	- returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err
+ *	when bootenv can't be read
+ *	- returns -PFIFLASH_ERR_BOOTENV_READ, err_buf matches text to err
+ *	when PDD handling function returns and error
+ *	- passes rc and err_buf data
+ *	when CRC check fails
+ *	- returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err
+ *	when bootenv can't be resized
+ *	- returns -PFIFLASH_ERR_BOOTENV_SIZE, err_buf matches text to err
+ *	when UBI system couldn't open a volume
+ *	- returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err
+ *	when couldn't write bootenv data
+ *	- returns -PFIFLASH_ERR_BOOTENV_WRITE, err_buf matches text to err
+ **/
+static int
+write_bootenv_volume(int devno, uint32_t id, bootenv_t bootenv_old,
+		     pdd_func_t pdd_f, FILE* fp_in, size_t fp_in_size,
+		     uint32_t pfi_crc,
+		     char *err_buf, size_t err_buf_size)
+{
+	int rc, warnings, fd_out;
+	uint32_t crc;
+	char path[PATH_MAX];
+	size_t update_size;
+	FILE *fp_out;
+	bootenv_t bootenv_new, bootenv_res;
+	libubi_t ulib;
+
+	rc = 0;
+	warnings = 0;
+	crc = 0;
+	update_size = 0;
+	fp_out = NULL;
+	bootenv_new = NULL;
+	bootenv_res = NULL;
+	ulib = NULL;
+
+	log_msg("[ ubiupdatevol bootenv id=%d, fp_in=%p", id, fp_in);
+
+	/* Workflow:
+	 * 1. Apply PDD operation and get the size of the returning
+	 *    bootenv_res section. Without the correct size it wouldn't
+	 *    be possible to call UBI update vol.
+	 * 2. Call UBI update vol
+	 * 3. Get FILE* to vol dev
+	 * 4. Write to FILE*
+	 */
+
+	ulib = libubi_open();
+	if (ulib == NULL) {
+		rc = -PFIFLASH_ERR_UBI_OPEN;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	}
+
+	rc = bootenv_create(&bootenv_new);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
+		EBUF(PFIFLASH_ERRSTR[-rc], " 'new'");
+		goto err;
+	}
+
+	rc = bootenv_create(&bootenv_res);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
+		EBUF(PFIFLASH_ERRSTR[-rc], " 'res'");
+		goto err;
+	}
+
+	rc = bootenv_read_crc(fp_in, bootenv_new, fp_in_size, &crc);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_READ;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	} else if (crc != pfi_crc) {
+		rc = -PFIFLASH_ERR_CRC_CHECK;
+		EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc);
+		goto err;
+	}
+
+	rc = pdd_f(bootenv_old, bootenv_new, &bootenv_res, &warnings,
+		   err_buf, err_buf_size);
+	if (rc != 0) {
+		EBUF_PREPEND("handling PDD");
+		goto err;
+	}
+	else if (warnings)
+		/* TODO do something with warnings */
+		dbg_msg("A warning in the PDD operation occured: %d",
+			warnings);
+
+	rc = bootenv_size(bootenv_res, &update_size);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_SIZE;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	}
+
+	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
+
+	fd_out = open(path, O_RDWR);
+	if (fd_out < 0) {
+		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
+		EBUF(PFIFLASH_ERRSTR[-rc], id);
+		goto err;
+	}
+	fp_out = fdopen(fd_out, "r+");
+	if (!fp_out) {
+		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
+		EBUF(PFIFLASH_ERRSTR[-rc], id);
+		goto err;
+	}
+	rc = ubi_update_start(ulib, fd_out, update_size);
+	if (rc < 0) {
+		rc = -PFIFLASH_ERR_UBI_VOL_UPDATE;
+		EBUF(PFIFLASH_ERRSTR[-rc], id);
+		goto err;
+	}
+
+	rc = bootenv_write(fp_out, bootenv_res);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_WRITE;
+		EBUF(PFIFLASH_ERRSTR[-rc], devno, id);
+		goto err;
+	}
+
+ err:
+	if (ulib != NULL)
+		libubi_close(ulib);
+	if (bootenv_new != NULL)
+		bootenv_destroy(&bootenv_new);
+	if (bootenv_res != NULL)
+		bootenv_destroy(&bootenv_res);
+	if (fp_out)
+		fclose(fp_out);
+
+	return rc;
+}
+
+
+/**
+ * write_normal_volume - writes data from PFI file int to regular UBI volume
+ * @devno	UBI device number
+ * @id		UBI volume id
+ * @update_size	size of data stream
+ * @fp_in	PFI data file pointer
+ * @pfi_crc	CRC data from PFI header
+ *
+ * Error handling:
+ *	when UBI system couldn't be opened
+ *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
+ *	when UBI system couldn't open a volume
+ *	- returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err
+ *	when unexpected EOF is encountered
+ *	- returns -PFIFLASH_ERR_EOF, err_buf matches text to err
+ *	when file I/O error
+ *	- returns -PFIFLASH_ERR_FIO, err_buf matches text to err
+ *	when CRC check fails
+ *	- retruns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err
+ **/
+static int
+write_normal_volume(int devno, uint32_t id, size_t update_size, FILE* fp_in,
+		    uint32_t pfi_crc,
+		    char *err_buf, size_t err_buf_size)
+{
+	int rc, fd_out;
+	uint32_t crc, crc32_table[256];
+	char path[PATH_MAX];
+	size_t bytes_left;
+	FILE* fp_out;
+	libubi_t ulib;
+
+	rc = 0;
+	crc = UBI_CRC32_INIT;
+	bytes_left = update_size;
+	fp_out = NULL;
+	ulib = NULL;
+
+	log_msg("[ ubiupdatevol id=%d, update_size=%d fp_in=%p",
+		id, update_size, fp_in);
+
+	ulib = libubi_open();
+	if (ulib == NULL) {
+		rc = -PFIFLASH_ERR_UBI_OPEN;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	}
+
+	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
+
+	fd_out = open(path, O_RDWR);
+	if (fd_out < 0) {
+		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
+		EBUF(PFIFLASH_ERRSTR[-rc], id);
+		goto err;
+	}
+	fp_out = fdopen(fd_out, "r+");
+	if (!fp_out) {
+		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
+		EBUF(PFIFLASH_ERRSTR[-rc], id);
+		goto err;
+	}
+	rc = ubi_update_start(ulib, fd_out, update_size);
+	if (rc < 0) {
+		rc = -PFIFLASH_ERR_UBI_VOL_UPDATE;
+		EBUF(PFIFLASH_ERRSTR[-rc], id);
+		goto err;
+	}
+
+	init_crc32_table(crc32_table);
+	while (bytes_left) {
+		char buf[1024];
+		size_t to_rw = sizeof buf > bytes_left ?
+			bytes_left : sizeof buf;
+		if (fread(buf, 1, to_rw, fp_in) != to_rw) {
+			rc = -PFIFLASH_ERR_EOF;
+			EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+			goto err;
+		}
+		crc = clc_crc32(crc32_table, crc, buf, to_rw);
+		if (fwrite(buf, 1, to_rw, fp_out) != to_rw) {
+			rc = -PFIFLASH_ERR_FIO;
+			EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+			goto err;
+		}
+		bytes_left -= to_rw;
+	}
+
+	if (crc != pfi_crc) {
+		rc = -PFIFLASH_ERR_CRC_CHECK;
+		EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc);
+		goto err;
+	}
+
+ err:
+	if (fp_out)
+		fclose(fp_out);
+	if (ulib)
+		libubi_close(ulib);
+
+	return rc;
+}
+
+static int compare_bootenv(FILE *fp_pfi, FILE **fp_flash, uint32_t ids_size,
+		uint32_t data_size, pdd_func_t pdd_f, char *err_buf,
+		size_t err_buf_size)
+{
+	int rc, warnings = 0;
+	unsigned int i;
+	bootenv_t bootenv_pfi, bootenv_res = NULL, bootenv_flash = NULL;
+
+	rc = bootenv_create(&bootenv_pfi);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
+		goto err;
+	}
+
+	rc = bootenv_create(&bootenv_res);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
+		goto err;
+	}
+
+	rc = bootenv_read(fp_pfi, bootenv_pfi, data_size);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_READ;
+		goto err;
+	}
+
+	for (i = 0; i < ids_size; i++) {
+		rc = bootenv_create(&bootenv_flash);
+		if (rc != 0) {
+			rc = -PFIFLASH_ERR_BOOTENV_CREATE;
+			goto err;
+		}
+
+		rc = bootenv_read(fp_flash[i], bootenv_flash, BOOTENV_MAXSIZE);
+		if (rc != 0) {
+			rc = -PFIFLASH_ERR_BOOTENV_READ;
+			goto err;
+		}
+
+		rc = pdd_f(bootenv_flash, bootenv_pfi, &bootenv_res,
+				&warnings, err_buf, err_buf_size);
+		if (rc != 0) {
+			rc = -PFIFLASH_ERR_PDD_UNKNOWN;
+			goto err;
+		}
+
+		rc = bootenv_compare(bootenv_flash, bootenv_res);
+		if (rc > 0) {
+			rc = -PFIFLASH_CMP_DIFF;
+			goto err;
+		} else if (rc < 0) {
+			rc = -PFIFLASH_ERR_COMPARE;
+			goto err;
+		}
+
+		bootenv_destroy(&bootenv_flash);
+		bootenv_flash = NULL;
+	}
+
+err:
+	if (bootenv_pfi)
+		bootenv_destroy(&bootenv_pfi);
+	if (bootenv_res)
+		bootenv_destroy(&bootenv_res);
+	if (bootenv_flash)
+		bootenv_destroy(&bootenv_flash);
+
+	return rc;
+}
+
+static int compare_data(FILE *fp_pfi, FILE **fp_flash, uint32_t ids_size,
+		uint32_t bytes_left)
+{
+	unsigned int i;
+	size_t read_bytes, rc = 0;
+	char buf_pfi[COMPARE_BUFFER_SIZE];
+	char *buf_flash[ids_size];
+
+	for (i = 0; i < ids_size; i++) {
+		buf_flash[i] = malloc(COMPARE_BUFFER_SIZE);
+		if (!buf_flash[i])
+			return -PFIFLASH_ERR_COMPARE;
+	}
+
+	while (bytes_left) {
+		if (bytes_left > COMPARE_BUFFER_SIZE)
+			read_bytes = COMPARE_BUFFER_SIZE;
+		else
+			read_bytes = bytes_left;
+
+		rc = fread(buf_pfi, 1, read_bytes, fp_pfi);
+		if (rc != read_bytes) {
+			rc = -PFIFLASH_ERR_COMPARE;
+			goto err;
+		}
+
+		for (i = 0; i < ids_size; i++) {
+			rc = fread(buf_flash[i], 1, read_bytes, fp_flash[i]);
+			if (rc != read_bytes) {
+				rc = -PFIFLASH_CMP_DIFF;
+				goto err;
+			}
+
+			rc = memcmp(buf_pfi, buf_flash[i], read_bytes);
+			if (rc != 0) {
+				rc = -PFIFLASH_CMP_DIFF;
+				goto err;
+			}
+		}
+
+		bytes_left -= read_bytes;
+	}
+
+err:
+	for (i = 0; i < ids_size; i++)
+		free(buf_flash[i]);
+
+	return rc;
+}
+
+static int compare_volumes(int devno, pfi_ubi_t u, FILE *fp_pfi,
+		pdd_func_t pdd_f, char *err_buf, size_t err_buf_size)
+{
+	int rc, is_bootenv = 0;
+	unsigned int i;
+	char path[PATH_MAX];
+	libubi_t ulib = NULL;
+	FILE *fp_flash[u->ids_size];
+
+	ulib = libubi_open();
+	if (ulib == NULL) {
+		rc = -PFIFLASH_ERR_UBI_OPEN;
+		goto err;
+	}
+
+	for (i = 0; i < u->ids_size; i++) {
+		if (u->ids[i] == EXAMPLE_BOOTENV_VOL_ID_1 ||
+		    u->ids[i] == EXAMPLE_BOOTENV_VOL_ID_2)
+			is_bootenv = 1;
+
+		snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, u->ids[i]);
+
+		fp_flash[i] = fopen(path, "r");
+		if (fp_flash[i] == NULL) {
+			rc = -PFIFLASH_ERR_UBI_OPEN;
+			goto err;
+		}
+	}
+
+	if (is_bootenv)
+		rc = compare_bootenv(fp_pfi, fp_flash, u->ids_size,
+				u->data_size, pdd_f, err_buf, err_buf_size);
+	else
+		rc = compare_data(fp_pfi, fp_flash, u->ids_size, u->data_size);
+
+err:
+	if (rc < 0)
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+
+	for (i = 0; i < u->ids_size; i++)
+		fclose(fp_flash[i]);
+	if (ulib)
+		libubi_close(ulib);
+
+	return rc;
+}
+
+static int
+erase_mtd_region(FILE* file_p, int start, int length)
+{
+	int rc, fd;
+	erase_info_t erase;
+	mtd_info_t mtdinfo;
+	loff_t offset = start;
+	loff_t end = offset + length;
+
+	fd = fileno(file_p);
+	if (fd < 0)
+		return -PFIFLASH_ERR_MTD_ERASE;
+
+	rc = ioctl(fd, MEMGETINFO, &mtdinfo);
+	if (rc)
+		return -PFIFLASH_ERR_MTD_ERASE;
+
+	/* check for bad blocks in case of NAND flash */
+	if (mtdinfo.type == MTD_NANDFLASH) {
+		while (offset < end) {
+			rc = ioctl(fd, MEMGETBADBLOCK, &offset);
+			if (rc > 0) {
+				return -PFIFLASH_ERR_MTD_ERASE;
+			}
+
+			offset += mtdinfo.erasesize;
+		}
+	}
+
+	erase.start = start;
+	erase.length = length;
+
+	rc = ioctl(fd, MEMERASE, &erase);
+	if (rc) {
+		return -PFIFLASH_ERR_MTD_ERASE;
+	}
+
+	return rc;
+}
+
+/**
+ * process_raw_volumes - writes the raw sections of the PFI data
+ * @pfi		PFI data file pointer
+ * @pfi_raws	list of PFI raw headers
+ * @rawdev	device to use to write raw data
+ *
+ * Error handling:
+ *	when early EOF in PFI data
+ *	- returns -PFIFLASH_ERR_EOF, err_buf matches text to err
+ *	when file I/O error
+ *	- returns -PFIFLASH_ERR_FIO, err_buf matches text to err
+ *	when CRC check fails
+ *	- returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err
+ *	when opening MTD device fails
+ *	- reutrns -PFIFLASH_ERR_MTD_OPEN, err_buf matches text to err
+ *	when closing MTD device fails
+ *	- returns -PFIFLASH_ERR_MTD_CLOSE, err_buf matches text to err
+ **/
+static int
+process_raw_volumes(FILE* pfi, list_t pfi_raws, const char* rawdev,
+		    char* err_buf, size_t err_buf_size)
+{
+	int rc;
+	char *pfi_data;
+	void *i;
+	uint32_t crc, crc32_table[256];
+	size_t j, k;
+	FILE* mtd = NULL;
+	list_t ptr;
+
+	if (is_empty(pfi_raws))
+		return 0;
+
+	if (rawdev == NULL)
+		return 0;
+
+	rc = 0;
+
+	pfi_data = NULL;
+
+	log_msg("[ rawupdate dev=%s", rawdev);
+
+	crc = UBI_CRC32_INIT;
+	init_crc32_table(crc32_table);
+
+	/* most likely only one element in list, but just in case */
+	foreach(i, ptr, pfi_raws) {
+		pfi_raw_t r = (pfi_raw_t)i;
+
+		/* read in pfi data */
+		if (pfi_data != NULL)
+			free(pfi_data);
+		pfi_data = malloc(r->data_size * sizeof(char));
+		for (j = 0; j < r->data_size; j++) {
+			int c = fgetc(pfi);
+			if (c == EOF) {
+				rc = -PFIFLASH_ERR_EOF;
+				EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+				goto err;
+			} else if (ferror(pfi)) {
+				rc = -PFIFLASH_ERR_FIO;
+				EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+				goto err;
+			}
+			pfi_data[j] = (char)c;
+		}
+		crc = clc_crc32(crc32_table, crc, pfi_data, r->data_size);
+
+		/* check crc */
+		if (crc != r->crc) {
+			rc = -PFIFLASH_ERR_CRC_CHECK;
+			EBUF(PFIFLASH_ERRSTR[-rc], r->crc, crc);
+			goto err;
+		}
+
+		/* open device */
+		mtd = fopen(rawdev, "r+");
+		if (mtd == NULL) {
+			rc = -PFIFLASH_ERR_MTD_OPEN;
+			EBUF(PFIFLASH_ERRSTR[-rc], rawdev);
+			goto err;
+		}
+
+		for (j = 0; j < r->starts_size; j++) {
+			rc = erase_mtd_region(mtd, r->starts[j], r->data_size);
+			if (rc) {
+				EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+				goto err;
+			}
+
+			fseek(mtd, r->starts[j], SEEK_SET);
+			for (k = 0; k < r->data_size; k++) {
+				int c = fputc((int)pfi_data[k], mtd);
+				if (c == EOF) {
+					fclose(mtd);
+					rc = -PFIFLASH_ERR_EOF;
+					EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+					goto err;
+				}
+				if ((char)c != pfi_data[k]) {
+					fclose(mtd);
+					rc = -1;
+					goto err;
+				}
+			}
+		}
+		rc = fclose(mtd);
+		mtd = NULL;
+		if (rc != 0) {
+			rc = -PFIFLASH_ERR_MTD_CLOSE;
+			EBUF(PFIFLASH_ERRSTR[-rc], rawdev);
+			goto err;
+		}
+	}
+
+ err:
+	if (mtd != NULL)
+		fclose(mtd);
+	if (pfi_data != NULL)
+		free(pfi_data);
+	return rc;
+}
+
+
+/**
+ * erase_unmapped_ubi_volumes - skip volumes provided by PFI file, clear rest
+ * @devno	UBI device number
+ * @pfi_ubis	list of UBI header data
+ *
+ * Error handling:
+ *	when UBI id is out of bounds
+ *	- returns -PFIFLASH_ERR_UBI_VID_OOB, err_buf matches text to err
+ *	when UBI volume can't be removed
+ *	- passes rc, prepends err_buf with contextual aid
+ **/
+static int
+erase_unmapped_ubi_volumes(int devno, list_t pfi_ubis,
+			   char *err_buf, size_t err_buf_size)
+{
+	int rc;
+	uint8_t ubi_volumes[PFI_UBI_MAX_VOLUMES];
+	size_t i;
+	list_t ptr;
+	pfi_ubi_t u;
+
+	rc = 0;
+
+	for (i = 0; i < PFI_UBI_MAX_VOLUMES; i++)
+		ubi_volumes[i] = 1;
+
+	foreach(u, ptr, pfi_ubis) {
+		/* iterate over each vol_id */
+		for(i = 0; i < u->ids_size; i++) {
+			if (u->ids[i] >= PFI_UBI_MAX_VOLUMES) {
+				rc = -PFIFLASH_ERR_UBI_VID_OOB;
+				EBUF(PFIFLASH_ERRSTR[-rc], u->ids[i]);
+				goto err;
+			}
+			/* remove from removal list */
+			ubi_volumes[u->ids[i]] = 0;
+		}
+	}
+
+	for (i = 0; i < PFI_UBI_MAX_VOLUMES; i++) {
+		if (ubi_volumes[i]) {
+			rc = my_ubi_rmvol(devno, i, err_buf, err_buf_size);
+			if (rc != 0) {
+				EBUF_PREPEND("remove volume failed");
+				goto err;
+			}
+		}
+	}
+
+ err:
+	return rc;
+}
+
+
+/**
+ * process_ubi_volumes - delegate tasks regarding UBI volumes
+ * @pfi			PFI data file pointer
+ * @seqnum		sequence number
+ * @pfi_ubis		list of UBI header data
+ * @bootenv_old		storage for current system PDD
+ * @pdd_f		function to handle PDD
+ * @ubi_update_process	whether reading or writing
+ *
+ * Error handling:
+ *	when and unknown ubi_update_process is given
+ *	- returns -PFIFLASH_ERR_UBI_UNKNOWN, err_buf matches text to err
+ *	otherwise
+ *	- passes rc and err_buf
+ **/
+static int
+process_ubi_volumes(FILE* pfi, int seqnum, list_t pfi_ubis,
+		    bootenv_t bootenv_old, pdd_func_t pdd_f,
+		    ubi_update_process_t ubi_update_process,
+		    char *err_buf, size_t err_buf_size)
+{
+	int rc;
+	pfi_ubi_t u;
+	list_t ptr;
+
+	rc = 0;
+
+	foreach(u, ptr, pfi_ubis) {
+		int s = seqnum;
+
+		if (s > ((int)u->ids_size - 1))
+			s = 0; /* per default use the first */
+		u->curr_seqnum = s;
+
+		switch (ubi_update_process) {
+		case UBI_REMOVE:
+			/* TODO are all these "EXAMPLE" vars okay? */
+			if ((u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_1) ||
+			    (u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_2)) {
+				rc = read_bootenv_volume(EXAMPLE_UBI_DEVICE,
+							 u->ids[s], bootenv_old,
+							 err_buf, err_buf_size);
+				/* it's okay if there is no bootenv
+				 * we're going to write one */
+				if ((rc == -PFIFLASH_ERR_UBI_VOL_FOPEN) ||
+				    (rc == -PFIFLASH_ERR_BOOTENV_READ))
+					rc = 0;
+				if (rc != 0)
+					goto err;
+			}
+
+			rc = my_ubi_rmvol(EXAMPLE_UBI_DEVICE, u->ids[s],
+					  err_buf, err_buf_size);
+			if (rc != 0)
+				goto err;
+
+			break;
+		case UBI_WRITE:
+			rc = my_ubi_mkvol(EXAMPLE_UBI_DEVICE, s, u,
+					  err_buf, err_buf_size);
+			if (rc != 0) {
+				EBUF_PREPEND("creating volume");
+				goto err;
+			}
+
+			if ((u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_1) ||
+			    (u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_2)) {
+				rc = write_bootenv_volume(EXAMPLE_UBI_DEVICE,
+							  u->ids[s],
+							  bootenv_old, pdd_f,
+							  pfi,
+							  u->data_size,
+							  u->crc,
+							  err_buf,
+							  err_buf_size);
+				if (rc != 0)
+					EBUF_PREPEND("bootenv volume");
+			} else {
+				rc = write_normal_volume(EXAMPLE_UBI_DEVICE,
+							 u->ids[s],
+							 u->data_size, pfi,
+							 u->crc,
+							 err_buf,
+							 err_buf_size);
+				if (rc != 0)
+					EBUF_PREPEND("normal volume");
+			}
+			if (rc != 0)
+				goto err;
+
+			break;
+		case UBI_COMPARE:
+			rc = compare_volumes(EXAMPLE_UBI_DEVICE, u, pfi, pdd_f,
+					err_buf, err_buf_size);
+			if (rc != 0) {
+				EBUF_PREPEND("compare volume");
+				goto err;
+			}
+
+			break;
+		default:
+			rc = -PFIFLASH_ERR_UBI_UNKNOWN;
+			EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+			goto err;
+		}
+	}
+
+ err:
+	return rc;
+}
+
+
+/**
+ * mirror_ubi_volumes - mirror redundant pairs of volumes
+ * @devno	UBI device number
+ * @pfi_ubis	list of PFI header data
+ *
+ * Error handling:
+ *	when UBI system couldn't be opened
+ *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
+ **/
+static int
+mirror_ubi_volumes(uint32_t devno, list_t pfi_ubis,
+		   char *err_buf, size_t err_buf_size)
+{
+	int rc;
+	uint32_t j;
+	list_t ptr;
+	pfi_ubi_t i;
+	libubi_t ulib;
+
+	rc = 0;
+	ulib = NULL;
+
+	log_msg("[ mirror ...");
+
+	ulib = libubi_open();
+	if (ulib == NULL) {
+		rc = -PFIFLASH_ERR_UBI_OPEN;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	}
+
+	/**
+	 * Execute all mirror operations on redundant groups.
+	 * Create a volume within a redundant group if it does
+	 * not exist already (this is a precondition of
+	 * ubimirror).
+	 */
+	foreach(i, ptr, pfi_ubis) {
+		for (j = 0; j < i->ids_size; j++) {
+			/* skip self-match */
+			if (i->ids[j] == i->ids[i->curr_seqnum])
+				continue;
+
+			rc = my_ubi_rmvol(devno, i->ids[j],
+					  err_buf, err_buf_size);
+			if (rc != 0)
+				goto err;
+
+			rc = my_ubi_mkvol(devno, j, i,
+					  err_buf, err_buf_size);
+			if (rc != 0)
+				goto err;
+		}
+	}
+
+	foreach(i, ptr, pfi_ubis) {
+		rc = ubimirror(devno, i->curr_seqnum, i->ids, i->ids_size,
+			       err_buf, err_buf_size);
+		if (rc != 0)
+			goto err;
+	}
+
+
+ err:
+	if (ulib != NULL)
+		libubi_close(ulib);
+
+	return rc;
+}
+
+
+/**
+ * pfiflash_with_options - exposed func to flash memory with a PFI file
+ * @pfi			PFI data file pointer
+ * @complete		flag to erase unmapped volumes
+ * @seqnum		sequence number
+ * @compare		flag to compare
+ * @pdd_handling	method to handle pdd (keep, merge, overwrite...)
+ *
+ * Error handling:
+ *	when bootenv can't be created
+ *	- returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err
+ *	when PFI headers can't be read, or
+ *	when fail to skip raw sections, or
+ *	when error occurs while processing raw volumes, or
+ *	when fail to erase unmapped UBI vols, or
+ *	when error occurs while processing UBI volumes, or
+ *	when error occurs while mirroring UBI volumes
+ *	- passes rc, prepends err_buf with contextual aid
+ **/
+int
+pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare,
+		  pdd_handling_t pdd_handling, const char* rawdev,
+		  char *err_buf, size_t err_buf_size)
+{
+	int rc;
+	bootenv_t bootenv;
+	pdd_func_t pdd_f;
+
+	if (pfi == NULL)
+		return -EINVAL;
+
+	rc = 0;
+	pdd_f = NULL;
+
+	/* If the user didnt specify a seqnum we start per default
+	 * with the index 0 */
+	int curr_seqnum = seqnum < 0 ? 0 : seqnum;
+
+	list_t pfi_raws   = mk_empty(); /* list of raw sections from a pfi */
+	list_t pfi_ubis   = mk_empty(); /* list of ubi sections from a pfi */
+
+	rc = bootenv_create(&bootenv);
+	if (rc != 0) {
+		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
+		EBUF(PFIFLASH_ERRSTR[-rc], "");
+		goto err;
+	}
+
+	rc = read_pfi_headers(&pfi_raws, &pfi_ubis, pfi, err_buf, err_buf_size);
+	if (rc != 0) {
+		EBUF_PREPEND("reading PFI header");
+		goto err;
+	}
+
+	if (rawdev == NULL || compare)
+		rc = skip_raw_volumes(pfi, pfi_raws, err_buf, err_buf_size);
+	else
+		rc = process_raw_volumes(pfi, pfi_raws, rawdev, err_buf,
+					 err_buf_size);
+	if (rc != 0) {
+		EBUF_PREPEND("handling raw section");
+		goto err;
+	}
+
+	if (complete && !compare) {
+		rc = erase_unmapped_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis,
+						err_buf, err_buf_size);
+		if (rc != 0) {
+			EBUF_PREPEND("deleting unmapped UBI volumes");
+			goto err;
+		}
+	}
+
+	if (((int)pdd_handling >= 0) &&
+	    (pdd_handling < PDD_HANDLING_NUM))
+		pdd_f = pdd_funcs[pdd_handling];
+	else {
+		rc = -PFIFLASH_ERR_PDD_UNKNOWN;
+		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
+		goto err;
+	}
+
+	if (!compare) {
+		rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv,
+				pdd_f, UBI_REMOVE, err_buf, err_buf_size);
+		if (rc != 0) {
+			EBUF_PREPEND("removing UBI volumes");
+			goto err;
+		}
+
+		rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv,
+				pdd_f, UBI_WRITE, err_buf, err_buf_size);
+		if  (rc != 0) {
+			EBUF_PREPEND("writing UBI volumes");
+			goto err;
+		}
+
+		if (seqnum < 0) { /* mirror redundant pairs */
+			rc = mirror_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis,
+					err_buf, err_buf_size);
+			if (rc != 0) {
+				EBUF_PREPEND("mirroring UBI volumes");
+				goto err;
+			}
+		}
+	} else {
+		/* only compare volumes, don't alter the content */
+		rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv,
+				pdd_f, UBI_COMPARE, err_buf, err_buf_size);
+
+		if (rc == -PFIFLASH_CMP_DIFF)
+			/* update is necessary, return positive value */
+			rc = 1;
+
+		if (rc < 0) {
+			EBUF_PREPEND("comparing UBI volumes");
+			goto err;
+		}
+	}
+
+ err:
+	pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws);
+	pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis);
+	bootenv_destroy(&bootenv);
+	return rc;
+}
+
+
+/**
+ * pfiflash - passes to pfiflash_with_options
+ * @pfi			PFI data file pointer
+ * @complete		flag to erase unmapped volumes
+ * @seqnum		sequence number
+ * @pdd_handling	method to handle pdd (keep, merge, overwrite...)
+ **/
+int
+pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling,
+		char *err_buf, size_t err_buf_size)
+{
+	return pfiflash_with_options(pfi, complete, seqnum, 0, pdd_handling,
+				 NULL, err_buf, err_buf_size);
+}
diff --git a/ubi-utils/old-utils/src/libubi.c b/ubi-utils/old-utils/src/libubi.c
new file mode 100644
index 0000000..a536b47
--- /dev/null
+++ b/ubi-utils/old-utils/src/libubi.c
@@ -0,0 +1,915 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Artem B. Bityutskiy
+ *
+ * UBI (Unsorted Block Images) library.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+#include "libubi.h"
+#include "libubi_int.h"
+
+libubi_t libubi_open(void)
+{
+	int fd, version;
+	struct libubi *lib;
+
+	lib = calloc(1, sizeof(struct libubi));
+	if (!lib)
+		return NULL;
+
+	/* TODO: this must be discovered instead */
+	lib->sysfs = strdup("/sys");
+	if (!lib->sysfs)
+		goto error;
+
+	lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI);
+	if (!lib->sysfs_ubi)
+		goto error;
+
+	/* Make sure UBI is present */
+	fd = open(lib->sysfs_ubi, O_RDONLY);
+	if (fd == -1)
+		goto error;
+	close(fd);
+
+	lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);
+	if (!lib->ubi_dev)
+		goto error;
+
+	lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);
+	if (!lib->ubi_version)
+		goto error;
+
+	lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);
+	if (!lib->dev_dev)
+		goto error;
+
+	lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);
+	if (!lib->dev_avail_ebs)
+		goto error;
+
+	lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);
+	if (!lib->dev_total_ebs)
+		goto error;
+
+	lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);
+	if (!lib->dev_bad_count)
+		goto error;
+
+	lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);
+	if (!lib->dev_eb_size)
+		goto error;
+
+	lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC);
+	if (!lib->dev_max_ec)
+		goto error;
+
+	lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD);
+	if (!lib->dev_bad_rsvd)
+		goto error;
+
+	lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS);
+	if (!lib->dev_max_vols)
+		goto error;
+
+	lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE);
+	if (!lib->dev_min_io_size)
+		goto error;
+
+	lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT);
+	if (!lib->ubi_vol)
+		goto error;
+
+	lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE);
+	if (!lib->vol_type)
+		goto error;
+
+	lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV);
+	if (!lib->vol_dev)
+		goto error;
+
+	lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT);
+	if (!lib->vol_alignment)
+		goto error;
+
+	lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES);
+	if (!lib->vol_data_bytes)
+		goto error;
+
+	lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS);
+	if (!lib->vol_rsvd_ebs)
+		goto error;
+
+	lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE);
+	if (!lib->vol_eb_size)
+		goto error;
+
+	lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED);
+	if (!lib->vol_corrupted)
+		goto error;
+
+	lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME);
+	if (!lib->vol_name)
+		goto error;
+
+	if (read_int(lib->ubi_version, &version))
+		goto error;
+	if (version != LIBUBI_UBI_VERSION) {
+		fprintf(stderr, "LIBUBI: this library was made for UBI version "
+				"%d, but UBI version %d is detected\n",
+			LIBUBI_UBI_VERSION, version);
+		goto error;
+	}
+
+	return lib;
+
+error:
+	free(lib->vol_corrupted);
+	free(lib->vol_eb_size);
+	free(lib->vol_rsvd_ebs);
+	free(lib->vol_data_bytes);
+	free(lib->vol_alignment);
+	free(lib->vol_dev);
+	free(lib->vol_type);
+	free(lib->ubi_vol);
+	free(lib->dev_min_io_size);
+	free(lib->dev_max_vols);
+	free(lib->dev_bad_rsvd);
+	free(lib->dev_max_ec);
+	free(lib->dev_eb_size);
+	free(lib->dev_bad_count);
+	free(lib->dev_total_ebs);
+	free(lib->dev_avail_ebs);
+	free(lib->dev_dev);
+	free(lib->ubi_version);
+	free(lib->ubi_dev);
+	free(lib->sysfs_ubi);
+	free(lib->sysfs);
+	free(lib);
+	return NULL;
+}
+
+void libubi_close(libubi_t desc)
+{
+	struct libubi *lib = (struct libubi *)desc;
+
+	free(lib->vol_name);
+	free(lib->vol_corrupted);
+	free(lib->vol_eb_size);
+	free(lib->vol_rsvd_ebs);
+	free(lib->vol_data_bytes);
+	free(lib->vol_alignment);
+	free(lib->vol_dev);
+	free(lib->vol_type);
+	free(lib->ubi_vol);
+	free(lib->dev_min_io_size);
+	free(lib->dev_max_vols);
+	free(lib->dev_bad_rsvd);
+	free(lib->dev_max_ec);
+	free(lib->dev_eb_size);
+	free(lib->dev_bad_count);
+	free(lib->dev_total_ebs);
+	free(lib->dev_avail_ebs);
+	free(lib->dev_dev);
+	free(lib->ubi_version);
+	free(lib->ubi_dev);
+	free(lib->sysfs_ubi);
+	free(lib->sysfs);
+	free(lib);
+}
+
+int ubi_get_info(libubi_t desc, struct ubi_info *info)
+{
+	DIR *sysfs_ubi;
+	struct dirent *dirent;
+	struct libubi *lib = (struct libubi *)desc;
+
+	memset(info, '\0', sizeof(struct ubi_info));
+
+	/*
+	 * We have to scan the UBI sysfs directory to identify how many UBI
+	 * devices are present.
+	 */
+	sysfs_ubi = opendir(lib->sysfs_ubi);
+	if (!sysfs_ubi)
+		return -1;
+
+	info->lowest_dev_num = INT_MAX;
+	while ((dirent = readdir(sysfs_ubi))) {
+		char *name = &dirent->d_name[0];
+		int dev_num, ret;
+
+		ret = sscanf(name, UBI_DEV_NAME_PATT, &dev_num);
+		if (ret == 1) {
+			info->dev_count += 1;
+			if (dev_num > info->highest_dev_num)
+				info->highest_dev_num = dev_num;
+			if (dev_num < info->lowest_dev_num)
+				info->lowest_dev_num = dev_num;
+		}
+	}
+
+	if (info->lowest_dev_num == INT_MAX)
+		info->lowest_dev_num = 0;
+
+	if (read_int(lib->ubi_version, &info->version))
+		goto close;
+
+	return closedir(sysfs_ubi);
+
+close:
+	closedir(sysfs_ubi);
+	return -1;
+}
+
+int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
+{
+	int fd, ret;
+	struct ubi_mkvol_req r;
+	size_t n;
+
+	desc = desc;
+	r.vol_id = req->vol_id;
+	r.alignment = req->alignment;
+	r.bytes = req->bytes;
+	r.vol_type = req->vol_type;
+
+	n = strlen(req->name);
+	if (n > UBI_MAX_VOLUME_NAME)
+		return -1;
+
+	strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
+	r.name_len = n;
+
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	ret = ioctl(fd, UBI_IOCMKVOL, &r);
+	if (!ret)
+		req->vol_id = r.vol_id;
+
+	close(fd);
+	return ret;
+}
+
+int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
+{
+	int fd, ret;
+
+	desc = desc;
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
+	close(fd);
+	return ret;
+}
+
+int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
+{
+	int fd, ret;
+	struct ubi_rsvol_req req;
+
+	desc = desc;
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	req.bytes = bytes;
+	req.vol_id = vol_id;
+
+	ret = ioctl(fd, UBI_IOCRSVOL, &req);
+	close(fd);
+	return ret;
+}
+
+int ubi_update_start(libubi_t desc, int fd, long long bytes)
+{
+	desc = desc;
+	if (ioctl(fd, UBI_IOCVOLUP, &bytes))
+		return -1;
+	return 0;
+}
+
+int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
+{
+	int dev_num;
+	struct libubi *lib = (struct libubi *)desc;
+
+	dev_num = find_dev_num(lib, node);
+	if (dev_num == -1)
+		return -1;
+
+	return ubi_get_dev_info1(desc, dev_num, info);
+}
+
+int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
+{
+	DIR *sysfs_ubi;
+	struct dirent *dirent;
+	struct libubi *lib = (struct libubi *)desc;
+
+	memset(info, '\0', sizeof(struct ubi_dev_info));
+	info->dev_num = dev_num;
+
+	sysfs_ubi = opendir(lib->sysfs_ubi);
+	if (!sysfs_ubi)
+		return -1;
+
+	info->lowest_vol_num = INT_MAX;
+	while ((dirent = readdir(sysfs_ubi))) {
+		char *name = &dirent->d_name[0];
+		int vol_id, ret, devno;
+
+		ret = sscanf(name, UBI_VOL_NAME_PATT, &devno, &vol_id);
+		if (ret == 2 && devno == dev_num) {
+			info->vol_count += 1;
+			if (vol_id > info->highest_vol_num)
+				info->highest_vol_num = vol_id;
+			if (vol_id < info->lowest_vol_num)
+				info->lowest_vol_num = vol_id;
+		}
+	}
+
+	closedir(sysfs_ubi);
+
+	if (info->lowest_vol_num == INT_MAX)
+		info->lowest_vol_num = 0;
+
+	if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_ebs))
+		return -1;
+	if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_ebs))
+		return -1;
+	if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
+		return -1;
+	if (dev_read_int(lib->dev_eb_size, dev_num, &info->eb_size))
+		return -1;
+	if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
+		return -1;
+	if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
+		return -1;
+	if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
+		return -1;
+	if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
+		return -1;
+
+	info->avail_bytes = info->avail_ebs * info->eb_size;
+	info->total_bytes = info->total_ebs * info->eb_size;
+
+	return 0;
+}
+
+int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
+{
+	int vol_id, dev_num;
+	struct libubi *lib = (struct libubi *)desc;
+
+	dev_num = find_dev_num_vol(lib, node);
+	if (dev_num == -1)
+		return -1;
+
+	vol_id = find_vol_num(lib, dev_num, node);
+	if (vol_id == -1)
+		return -1;
+
+	return ubi_get_vol_info1(desc, dev_num, vol_id, info);
+}
+
+int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
+		      struct ubi_vol_info *info)
+{
+	int ret;
+	struct libubi *lib = (struct libubi *)desc;
+	char buf[50];
+
+	memset(info, '\0', sizeof(struct ubi_vol_info));
+	info->dev_num = dev_num;
+	info->vol_id = vol_id;
+
+	ret = vol_read_data(lib->vol_type, dev_num, vol_id, &buf[0], 50);
+	if (ret < 0)
+		return -1;
+
+	if (strncmp(&buf[0], "static\n", ret) == 0)
+		info->type = UBI_STATIC_VOLUME;
+	else if (strncmp(&buf[0], "dynamic\n", ret) == 0)
+		info->type = UBI_DYNAMIC_VOLUME;
+	else {
+		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
+			   &info->alignment);
+	if (ret)
+		return -1;
+	ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
+			  &info->data_bytes);
+	if (ret)
+		return -1;
+	ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_ebs);
+	if (ret)
+		return -1;
+	ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->eb_size);
+	if (ret)
+		return -1;
+	ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
+			   &info->corrupted);
+	if (ret)
+		return -1;
+	info->rsvd_bytes = info->eb_size * info->rsvd_ebs;
+
+	ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
+			    UBI_VOL_NAME_MAX + 2);
+	if (ret < 0)
+		return -1;
+
+	info->name[ret - 1] = '\0';
+	return 0;
+}
+
+/**
+ * read_int - read an 'int' value from a file.
+ *
+ * @file   the file to read from
+ * @value  the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int read_int(const char *file, int *value)
+{
+	int fd, rd;
+	char buf[50];
+
+	fd = open(file, O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, &buf[0], 50);
+	if (rd == -1)
+		goto error;
+
+	if (sscanf(&buf[0], "%d\n", value) != 1) {
+		/* This must be a UBI bug */
+		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+		errno = EINVAL;
+		goto error;
+	}
+
+	close(fd);
+	return 0;
+
+error:
+	close(fd);
+	return -1;
+}
+
+/**
+ * dev_read_int - read an 'int' value from an UBI device's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @value    the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_int(const char *patt, int dev_num, int *value)
+{
+	int fd, rd;
+	char buf[50];
+	char file[strlen(patt) + 50];
+
+	sprintf(&file[0], patt, dev_num);
+	fd = open(&file[0], O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, &buf[0], 50);
+	if (rd == -1)
+		goto error;
+
+	if (sscanf(&buf[0], "%d\n", value) != 1) {
+		/* This must be a UBI bug */
+		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+		errno = EINVAL;
+		goto error;
+	}
+
+	close(fd);
+	return 0;
+
+error:
+	close(fd);
+	return -1;
+}
+
+/**
+ * dev_read_ll - read a 'long long' value from an UBI device's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @value    the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_ll(const char *patt, int dev_num, long long *value)
+{
+	int fd, rd;
+	char buf[50];
+	char file[strlen(patt) + 50];
+
+	sprintf(&file[0], patt, dev_num);
+	fd = open(&file[0], O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, &buf[0], 50);
+	if (rd == -1)
+		goto error;
+
+	if (sscanf(&buf[0], "%lld\n", value) != 1) {
+		/* This must be a UBI bug */
+		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+		errno = EINVAL;
+		goto error;
+	}
+
+	close(fd);
+	return 0;
+
+error:
+	close(fd);
+	return -1;
+}
+
+/**
+ * dev_read_data - read data from an UBI device's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @buf      buffer to read data to
+ * @buf_len  buffer length
+ *
+ * This function returns number of read bytes in case of success and %-1 in
+ * case of failure.
+ */
+static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len)
+{
+	int fd, rd;
+	char file[strlen(patt) + 50];
+
+	sprintf(&file[0], patt, dev_num);
+	fd = open(&file[0], O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, buf, buf_len);
+	if (rd == -1) {
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+	return rd;
+}
+
+/**
+ * vol_read_int - read an 'int' value from an UBI volume's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @vol_id   volume identifier
+ * @value    the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
+{
+	int fd, rd;
+	char buf[50];
+	char file[strlen(patt) + 100];
+
+	sprintf(&file[0], patt, dev_num, vol_id);
+	fd = open(&file[0], O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, &buf[0], 50);
+	if (rd == -1)
+		goto error;
+
+	if (sscanf(&buf[0], "%d\n", value) != 1) {
+		/* This must be a UBI bug */
+		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+		errno = EINVAL;
+		goto error;
+	}
+
+	close(fd);
+	return 0;
+
+error:
+	close(fd);
+	return -1;
+}
+
+/**
+ * vol_read_ll - read a 'long long' value from an UBI volume's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @vol_id   volume identifier
+ * @value    the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_ll(const char *patt, int dev_num, int vol_id,
+		       long long *value)
+{
+	int fd, rd;
+	char buf[50];
+	char file[strlen(patt) + 100];
+
+	sprintf(&file[0], patt, dev_num, vol_id);
+	fd = open(&file[0], O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, &buf[0], 50);
+	if (rd == -1)
+		goto error;
+
+	if (sscanf(&buf[0], "%lld\n", value) != 1) {
+		/* This must be a UBI bug */
+		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+		errno = EINVAL;
+		goto error;
+	}
+
+	close(fd);
+	return 0;
+
+error:
+	close(fd);
+	return -1;
+}
+
+/**
+ * vol_read_data - read data from an UBI volume's sysfs file.
+ *
+ * @patt     the file pattern to read from
+ * @dev_num  UBI device number
+ * @vol_id   volume identifier
+ * @buf      buffer to read to
+ * @buf_len  buffer length
+ *
+ * This function returns number of read bytes in case of success and %-1 in
+ * case of failure.
+ */
+static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
+			 int buf_len)
+{
+	int fd, rd;
+	char file[strlen(patt) + 100];
+
+	sprintf(&file[0], patt, dev_num, vol_id);
+	fd = open(&file[0], O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, buf, buf_len);
+	if (rd == -1) {
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+	return rd;
+}
+
+/**
+ * mkpath - compose full path from 2 given components.
+ *
+ * @path  first component
+ * @name  second component
+ *
+ * This function returns the resulting path in case of success and %NULL in
+ * case of failure.
+ */
+static char *mkpath(const char *path, const char *name)
+{
+	char *n;
+	int len1 = strlen(path);
+	int len2 = strlen(name);
+
+	n = malloc(len1 + len2 + 2);
+	if (!n)
+		return NULL;
+
+	memcpy(n, path, len1);
+	if (n[len1 - 1] != '/')
+		n[len1++] = '/';
+
+	memcpy(n + len1, name, len2 + 1);
+	return n;
+}
+
+/**
+ * find_dev_num - find UBI device number by its character device node.
+ *
+ * @lib   UBI library descriptor
+ * @node  UBI character device node name
+ *
+ * This function returns positive UBI device number in case of success and %-1
+ * in case of failure.
+ */
+static int find_dev_num(struct libubi *lib, const char *node)
+{
+	struct stat st;
+	struct ubi_info info;
+	int i, major, minor;
+
+	if (stat(node, &st))
+		return -1;
+
+	if (!S_ISCHR(st.st_mode)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	major = major(st.st_rdev);
+	minor = minor(st.st_rdev);
+
+	if (minor != 0) {
+		errno = -EINVAL;
+		return -1;
+	}
+
+	if (ubi_get_info((libubi_t *)lib, &info))
+		return -1;
+
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		int major1, minor1, ret;
+		char buf[50];
+
+		ret = dev_read_data(lib->dev_dev, i, &buf[0], 50);
+		if (ret < 0)
+			return -1;
+
+		ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
+		if (ret != 2) {
+			fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+			errno = EINVAL;
+			return -1;
+		}
+
+		if (minor1 == minor && major1 == major)
+			return i;
+	}
+
+	errno = ENOENT;
+	return -1;
+}
+
+/**
+ * find_dev_num_vol - find UBI device number by volume character device node.
+ *
+ * @lib   UBI library descriptor
+ * @node  UBI character device node name
+ *
+ * This function returns positive UBI device number in case of success and %-1
+ * in case of failure.
+ */
+static int find_dev_num_vol(struct libubi *lib, const char *node)
+{
+	struct stat st;
+	struct ubi_info info;
+	int i, major;
+
+	if (stat(node, &st))
+		return -1;
+
+	if (!S_ISCHR(st.st_mode)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	major = major(st.st_rdev);
+
+	if (minor(st.st_rdev) == 0) {
+		errno = -EINVAL;
+		return -1;
+	}
+
+	if (ubi_get_info((libubi_t *)lib, &info))
+		return -1;
+
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		int major1, minor1, ret;
+		char buf[50];
+
+		ret = dev_read_data(lib->dev_dev, i, &buf[0], 50);
+		if (ret < 0)
+			return -1;
+
+		ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
+		if (ret != 2) {
+			fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+			errno = EINVAL;
+			return -1;
+		}
+
+		if (major1 == major)
+			return i;
+	}
+
+	errno = ENOENT;
+	return -1;
+}
+
+/**
+ * find_vol_num - find UBI volume number by its character device node.
+ *
+ * @lib      UBI library descriptor
+ * @dev_num  UBI device number
+ * @node     UBI volume character device node name
+ *
+ * This function returns positive UBI volume number in case of success and %-1
+ * in case of failure.
+ */
+static int find_vol_num(struct libubi *lib, int dev_num, const char *node)
+{
+	struct stat st;
+	struct ubi_dev_info info;
+	int i, major, minor;
+
+	if (stat(node, &st))
+		return -1;
+
+	if (!S_ISCHR(st.st_mode)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	major = major(st.st_rdev);
+	minor = minor(st.st_rdev);
+
+	if (minor == 0) {
+		errno = -EINVAL;
+		return -1;
+	}
+
+	if (ubi_get_dev_info1((libubi_t *)lib, dev_num, &info))
+		return -1;
+
+	for (i = info.lowest_vol_num; i <= info.highest_vol_num; i++) {
+		int major1, minor1, ret;
+		char buf[50];
+
+		ret = vol_read_data(lib->vol_dev,  dev_num, i, &buf[0], 50);
+		if (ret < 0)
+			return -1;
+
+		ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
+		if (ret != 2) {
+			fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+			errno = EINVAL;
+			return -1;
+		}
+
+		if (minor1 == minor && major1 == major)
+			return i;
+	}
+
+	errno = ENOENT;
+	return -1;
+}
diff --git a/ubi-utils/old-utils/src/libubi_int.h b/ubi-utils/old-utils/src/libubi_int.h
new file mode 100644
index 0000000..e68b791
--- /dev/null
+++ b/ubi-utils/old-utils/src/libubi_int.h
@@ -0,0 +1,129 @@
+/*
+ * 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_INT_H__
+#define __LIBUBI_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * UBI heavily makes use of the sysfs file system to interact with users-pace.
+ * The below are pre-define UBI file and directory names.
+ */
+
+#define SYSFS_UBI         "class/ubi"
+#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"
+#define DEV_EB_SIZE       "eraseblock_size"
+#define DEV_MAX_EC        "max_ec"
+#define DEV_MAX_RSVD      "reserved_for_bad"
+#define DEV_MAX_VOLS      "max_vol_count"
+#define DEV_MIN_IO_SIZE   "min_io_size"
+#define VOL_TYPE          "type"
+#define VOL_DEV           "dev"
+#define VOL_ALIGNMENT     "alignment"
+#define VOL_DATA_BYTES    "data_bytes"
+#define VOL_RSVD_EBS      "reserved_ebs"
+#define VOL_EB_SIZE       "usable_eb_size"
+#define VOL_CORRUPTED     "corrupted"
+#define VOL_NAME          "name"
+
+/**
+ * libubi - UBI library description data structure.
+ *
+ * @sysfs            sysfs file system path
+ * @sysfs_ubi        UBI directory in sysfs
+ * @ubi_dev          UBI device sysfs directory pattern
+ * @ubi_version      UBI version file sysfs path
+ * @dev_dev          UBI device's major/minor numbers file pattern
+ * @dev_avail_ebs    count of available eraseblocks sysfs path pattern
+ * @dev_total_ebs    total eraseblocks count sysfs path pattern
+ * @dev_bad_count    count of bad eraseblocks sysfs path pattern
+ * @dev_eb_size      size of UBI device's eraseblocks sysfs path pattern
+ * @dev_max_ec       maximum erase counter sysfs path pattern
+ * @dev_bad_rsvd     count of physical eraseblock reserved for bad eraseblocks
+ *                   handling
+ * @dev_max_vols     maximum volumes number count sysfs path pattern
+ * @dev_min_io_size  minimum I/O unit size sysfs path pattern
+ * @ubi_vol          UBI volume sysfs directory pattern
+ * @vol_type         volume type sysfs path pattern
+ * @vol_dev          volume's major/minor numbers file pattern
+ * @vol_alignment    volume alignment sysfs path pattern
+ * @vol_data_bytes   volume data size sysfs path pattern
+ * @vol_rsvd_ebs     volume reserved size sysfs path pattern
+ * @vol_eb_size      volume eraseblock size sysfs path pattern
+ * @vol_corrupted    volume corruption flag sysfs path pattern
+ * @vol_name         volume name sysfs path pattern
+ */
+struct libubi
+{
+	char *sysfs;
+	char *sysfs_ubi;
+	char *ubi_dev;
+	char *ubi_version;
+	char *dev_dev;
+	char *dev_avail_ebs;
+	char *dev_total_ebs;
+	char *dev_bad_count;
+	char *dev_eb_size;
+	char *dev_max_ec;
+	char *dev_bad_rsvd;
+	char *dev_max_vols;
+	char *dev_min_io_size;
+	char *ubi_vol;
+	char *vol_type;
+	char *vol_dev;
+	char *vol_alignment;
+	char *vol_data_bytes;
+	char *vol_rsvd_ebs;
+	char *vol_eb_size;
+	char *vol_corrupted;
+	char *vol_name;
+	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
+
+#endif /* !__LIBUBI_INT_H__ */
diff --git a/ubi-utils/old-utils/src/libubigen.c b/ubi-utils/old-utils/src/libubigen.c
new file mode 100644
index 0000000..1793009
--- /dev/null
+++ b/ubi-utils/old-utils/src/libubigen.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Oliver Lohmann
+ *
+ * Add UBI headers to binary data.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <mtd/ubi-media.h>
+#include <mtd_swab.h>
+
+#include "config.h"
+#include "ubigen.h"
+#include "crc32.h"
+
+#define UBI_NAME_SIZE		256
+#define DEFAULT_VID_OFFSET	((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE))
+#define MIN(a,b)		((a) < (b) ? (a) : (b))
+
+static uint32_t crc32_table[256];
+
+struct ubi_info {
+	struct ubi_vid_hdr* v;	/* Volume ID header */
+	struct ubi_ec_hdr* ec;	/* Erase count header */
+
+	FILE* fp_in;		/* Input Stream */
+	FILE* fp_out;		/* Output stream */
+
+	size_t eb_size;		/* Physical EB size in bytes */
+	size_t leb_size;	/* Size of a logical EB in a physical EB */
+	size_t leb_total;	/* Total input size in logical EB */
+	size_t alignment;	/* Block alignment */
+	size_t data_pad;	/* Size of padding in each physical EB */
+
+	size_t bytes_total;	/* Total input size in bytes */
+	size_t bytes_read;	/* Nymber of read bytes (total) */
+
+	uint32_t blks_written;	/* Number of written logical EB */
+
+	uint8_t* buf;		/* Allocated buffer */
+	uint8_t* ptr_ec_hdr;	/* Pointer to EC hdr in buf */
+	uint8_t* ptr_vid_hdr;	/* Pointer to VID hdr in buf */
+	uint8_t* ptr_data;	/* Pointer to data region in buf */
+};
+
+
+static uint32_t
+byte_to_blk(uint64_t byte, uint32_t eb_size)
+{
+	return (byte % eb_size) == 0
+		? (byte / eb_size)
+		: (byte / eb_size) + 1;
+}
+
+static int
+validate_ubi_info(ubi_info_t u)
+{
+	if ((u->v->vol_type != UBI_VID_DYNAMIC) &&
+	    (u->v->vol_type != UBI_VID_STATIC)) {
+		return EUBIGEN_INVALID_TYPE;
+	}
+
+	if (be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) {
+		return EUBIGEN_INVALID_HDR_OFFSET;
+	}
+
+	return 0;
+}
+
+static int
+skip_blks(ubi_info_t u, uint32_t blks)
+{
+	uint32_t i;
+	size_t read = 0, to_read = 0;
+
+	/* Step to a maximum of leb_total - 1 to keep the
+	   restrictions. */
+	for (i = 0; i < MIN(blks, u->leb_total-1); i++) {
+		/* Read in data */
+		to_read = MIN(u->leb_size,
+			      (u->bytes_total - u->bytes_read));
+		read = fread(u->ptr_data, 1, to_read, u->fp_in);
+		if (read != to_read) {
+			return -EIO;
+		}
+		u->bytes_read += read;
+		u->blks_written++;
+	}
+
+	return 0;
+}
+
+static void
+clear_buf(ubi_info_t u)
+{
+	memset(u->buf, 0xff, u->eb_size);
+}
+
+static void
+write_ec_hdr(ubi_info_t u)
+{
+	memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE);
+}
+
+static int
+fill_data_buffer_from_file(ubi_info_t u, size_t* read)
+{
+	size_t to_read = 0;
+
+	if (u-> fp_in == NULL)
+		return -EIO;
+
+	to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read));
+	*read = fread(u->ptr_data, 1, to_read, u->fp_in);
+	if (*read != to_read) {
+		return -EIO;
+	}
+	return 0;
+}
+
+static void
+add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action)
+{
+	uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+				 u->ptr_data, data_size);
+
+	u->v->data_size = cpu_to_be32(data_size);
+	u->v->data_crc = cpu_to_be32(crc);
+
+	if (action & BROKEN_DATA_CRC) {
+		u->v->data_crc =
+			cpu_to_be32(be32_to_cpu(u->v->data_crc) + 1);
+	}
+	if (action & BROKEN_DATA_SIZE) {
+		u->v->data_size =
+			cpu_to_be32(be32_to_cpu(u->v->data_size) + 1);
+	}
+}
+
+static void
+write_vid_hdr(ubi_info_t u, ubigen_action_t action)
+{
+	uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+				 u->v, UBI_VID_HDR_SIZE_CRC);
+	/* Write VID header */
+	u->v->hdr_crc = cpu_to_be32(crc);
+	if (action & BROKEN_HDR_CRC) {
+		u->v->hdr_crc = cpu_to_be32(be32_to_cpu(u->v->hdr_crc) + 1);
+	}
+	memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE);
+}
+
+static int
+write_to_output_stream(ubi_info_t u)
+{
+	size_t written;
+
+	written = fwrite(u->buf, 1, u->eb_size, u->fp_out);
+	if (written != u->eb_size) {
+		return -EIO;
+	}
+	return 0;
+}
+
+int
+ubigen_write_leb(ubi_info_t u, ubigen_action_t action)
+{
+	int rc = 0;
+	size_t read = 0;
+
+	clear_buf(u);
+	write_ec_hdr(u);
+
+	rc = fill_data_buffer_from_file(u, &read);
+	if (rc != 0)
+		return rc;
+
+	if (u->v->vol_type == UBI_VID_STATIC)  {
+		add_static_info(u, read, action);
+	}
+
+	u->v->lnum = cpu_to_be32(u->blks_written);
+
+	if (action & MARK_AS_UPDATE) {
+		u->v->copy_flag = (u->v->copy_flag)++;
+	}
+
+	write_vid_hdr(u, action);
+	rc = write_to_output_stream(u);
+	if (rc != 0)
+		return rc;
+
+	/* Update current handle */
+	u->bytes_read += read;
+	u->blks_written++;
+	return 0;
+}
+
+int
+ubigen_write_complete(ubi_info_t u)
+{
+	size_t i;
+	int rc = 0;
+
+	for (i = 0; i < u->leb_total; i++) {
+		rc = ubigen_write_leb(u,  NO_ERROR);
+		if (rc != 0)
+			return rc;
+	}
+
+	return 0;
+}
+
+int
+ubigen_write_broken_update(ubi_info_t u, uint32_t blk)
+{
+	int rc = 0;
+
+	rc = skip_blks(u, blk);
+	if (rc != 0)
+		return rc;
+
+	rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC);
+	if (rc != 0)
+		return rc;
+
+
+	return 0;
+}
+
+void
+dump_info(ubi_info_t u ubi_unused)
+{
+#ifdef DEBUG
+	int err = 0;
+	if (!u) {
+		fprintf(stderr, "<empty>");
+		return;
+	}
+	if (!u->ec) {
+		fprintf(stderr, "<ec-empty>");
+		err = 1;
+	}
+	if (!u->v) {
+		fprintf(stderr, "<v-empty>");
+		err = 1;
+	}
+	if (err) return;
+
+	fprintf(stderr, "ubi volume\n");
+	fprintf(stderr, "version      :	  %8d\n", u->v->version);
+	fprintf(stderr, "vol_id	      :	  %8d\n", be32_to_cpu(u->v->vol_id));
+	fprintf(stderr, "vol_type     :	  %8s\n",
+		u->v->vol_type == UBI_VID_STATIC ?
+		"static" : "dynamic");
+	fprintf(stderr, "used_ebs     :	  %8d\n",
+		be32_to_cpu(u->v->used_ebs));
+	fprintf(stderr, "eb_size      : 0x%08x\n", u->eb_size);
+	fprintf(stderr, "leb_size     : 0x%08x\n", u->leb_size);
+	fprintf(stderr, "data_pad     : 0x%08x\n",
+		be32_to_cpu(u->v->data_pad));
+	fprintf(stderr, "leb_total    :	  %8d\n", u->leb_total);
+	fprintf(stderr, "header offs  : 0x%08x\n",
+		be32_to_cpu(u->ec->vid_hdr_offset));
+	fprintf(stderr, "bytes_total  :	  %8d\n", u->bytes_total);
+	fprintf(stderr, "  +  in MiB  : %8.2f M\n",
+		((float)(u->bytes_total)) / 1024 / 1024);
+	fprintf(stderr, "-------------------------------\n\n");
+#else
+	return;
+#endif
+}
+
+int
+ubigen_destroy(ubi_info_t *u)
+{
+	if (u == NULL)
+		return -EINVAL;
+
+	ubi_info_t tmp = *u;
+
+	if (tmp) {
+		if (tmp->v)
+			free(tmp->v);
+		if (tmp->ec)
+			free(tmp->ec);
+		if (tmp->buf)
+			free(tmp->buf);
+		free(tmp);
+	}
+	*u = NULL;
+	return 0;
+}
+
+void
+ubigen_init(void)
+{
+	init_crc32_table(crc32_table);
+}
+
+int
+ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type,
+	      uint32_t eb_size, uint64_t ec, uint32_t alignment,
+	      uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag,
+	      size_t data_size, FILE* fp_in, FILE* fp_out)
+{
+	int rc = 0;
+	ubi_info_t res = NULL;
+	uint32_t crc;
+	uint32_t data_offset;
+
+	if (alignment == 0) {
+		rc = EUBIGEN_INVALID_ALIGNMENT;
+		goto ubigen_create_err;
+	}
+	if ((fp_in == NULL) || (fp_out == NULL)) {
+		rc = -EINVAL;
+		goto ubigen_create_err;
+	}
+
+	res = (ubi_info_t) calloc(1, sizeof(struct ubi_info));
+	if (res == NULL) {
+		rc = -ENOMEM;
+		goto ubigen_create_err;
+	}
+
+	res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr));
+	if (res->v == NULL) {
+		rc = -ENOMEM;
+		goto ubigen_create_err;
+	}
+
+	res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr));
+	if (res->ec == NULL) {
+		rc = -ENOMEM;
+		goto ubigen_create_err;
+	}
+
+	/* data which is needed in the general process */
+	vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET;
+	data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE;
+	res->bytes_total = data_size;
+	res->eb_size = eb_size ? eb_size : DEFAULT_BLOCKSIZE;
+	res->data_pad = (res->eb_size - data_offset) % alignment;
+	res->leb_size = res->eb_size - data_offset - res->data_pad;
+	res->leb_total = byte_to_blk(data_size, res->leb_size);
+	res->alignment = alignment;
+
+	if ((res->eb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) {
+		rc = EUBIGEN_TOO_SMALL_EB;
+		goto ubigen_create_err;
+	}
+	res->fp_in = fp_in;
+	res->fp_out = fp_out;
+
+	/* vid hdr data which doesn't change */
+	res->v->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
+	res->v->version = version ? version : UBI_VERSION;
+	res->v->vol_type = vol_type;
+	res->v->vol_id = cpu_to_be32(vol_id);
+	res->v->compat = compat_flag;
+	res->v->data_pad = cpu_to_be32(res->data_pad);
+
+	/* static only: used_ebs */
+	if (res->v->vol_type == UBI_VID_STATIC) {
+		res->v->used_ebs = cpu_to_be32(byte_to_blk
+						(res->bytes_total,
+						 res->leb_size));
+	}
+
+	/* ec hdr (fixed, doesn't change) */
+	res->ec->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
+	res->ec->version = version ? version : UBI_VERSION;
+	res->ec->ec = cpu_to_be64(ec);
+	res->ec->vid_hdr_offset = cpu_to_be32(vid_hdr_offset);
+
+	res->ec->data_offset = cpu_to_be32(data_offset);
+
+	crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec,
+			UBI_EC_HDR_SIZE_CRC);
+	res->ec->hdr_crc = cpu_to_be32(crc);
+
+	/* prepare a read buffer */
+	res->buf = (uint8_t*) malloc (res->eb_size * sizeof(uint8_t));
+	if (res->buf == NULL) {
+		rc = -ENOMEM;
+		goto ubigen_create_err;
+	}
+
+	/* point to distinct regions within the buffer */
+	res->ptr_ec_hdr = res->buf;
+	res->ptr_vid_hdr = res->buf + be32_to_cpu(res->ec->vid_hdr_offset);
+	res->ptr_data = res->buf + be32_to_cpu(res->ec->vid_hdr_offset)
+		+ UBI_VID_HDR_SIZE;
+
+	rc = validate_ubi_info(res);
+	if (rc != 0) {
+		fprintf(stderr, "Volume validation failed: %d\n", rc);
+		goto ubigen_create_err;
+	}
+
+	dump_info(res);
+	*u = res;
+	return rc;
+
+ ubigen_create_err:
+	if (res) {
+		if (res->v)
+			free(res->v);
+		if (res->ec)
+			free(res->ec);
+		if (res->buf)
+			free(res->buf);
+		free(res);
+	}
+	*u = NULL;
+	return rc;
+}
+
+int
+ubigen_get_leb_size(ubi_info_t u, size_t* size)
+{
+	if (u == NULL)
+		return -EINVAL;
+
+	*size = u->leb_size;
+	return 0;
+}
+
+
+int
+ubigen_get_leb_total(ubi_info_t u, size_t* total)
+{
+	if (u == NULL)
+		return -EINVAL;
+
+	*total = u->leb_total;
+	return 0;
+}
+
+int
+ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes,
+		    const char* vol_name, struct ubi_vtbl_record *lvol_rec)
+{
+	uint32_t crc;
+
+	if ((u == NULL) || (vol_name == NULL))
+		return -EINVAL;
+
+	memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE);
+
+	lvol_rec->reserved_pebs =
+		cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size));
+	lvol_rec->alignment = cpu_to_be32(u->alignment);
+	lvol_rec->data_pad = u->v->data_pad;
+	lvol_rec->vol_type = u->v->vol_type;
+
+	lvol_rec->name_len =
+		cpu_to_be16((uint16_t)strlen((const char*)vol_name));
+
+	memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1);
+
+	crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+			lvol_rec, UBI_VTBL_RECORD_SIZE_CRC);
+	lvol_rec->crc =	 cpu_to_be32(crc);
+
+	return 0;
+}
diff --git a/ubi-utils/old-utils/src/libubimirror.c b/ubi-utils/old-utils/src/libubimirror.c
new file mode 100644
index 0000000..d06770e
--- /dev/null
+++ b/ubi-utils/old-utils/src/libubimirror.c
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <memory.h>
+#include <limits.h>
+#include <fcntl.h>
+
+#include <libubi.h>
+#include "ubimirror.h"
+
+#define COMPARE_BUF_SIZE    (128 * 1024)
+
+#define DEFAULT_DEV_PATTERN    "/dev/ubi%d"
+#define DEFAULT_VOL_PATTERN    "/dev/ubi%d_%d"
+
+#define EBUF(fmt...) do {			\
+	snprintf(err_buf, err_buf_size, fmt);	\
+} while (0)
+
+enum {
+	compare_error = -1,
+	seek_error = -2,
+	write_error = -3,
+	read_error = -4,
+	update_error = -5,
+	ubi_error = -6,
+	open_error = -7,
+	close_error = -8,
+	compare_equal = 0,
+	compare_different = 1
+};
+
+/*
+ * Read len number of bytes from fd.
+ * Return 0 on EOF, -1 on error.
+ */
+static ssize_t fill_buffer(int fd, unsigned char *buf, ssize_t len)
+{
+	ssize_t got, have = 0;
+
+	do {
+		got = read(fd, buf + have, len - have);
+		if (got == -1 && errno != EINTR)
+			return -1;
+		have += got;
+	} while (got > 0 && have < len);
+	return have;
+}
+
+/*
+ * Write len number of bytes to fd.
+ * Return bytes written (>= 0), -1 on error.
+ */
+static ssize_t flush_buffer(int fd, unsigned char *buf, ssize_t len)
+{
+	ssize_t done, have = 0;
+
+	do {
+		done = write(fd, buf + have, len - have);
+		if (done == -1 && errno != EINTR)
+			return -1;
+		have += done;
+	} while (done > 0 && have < len);
+	return have;
+}
+
+/*
+ *  Compare two files.  Return 0, 1, or -1, depending on whether the
+ *  files are equal, different, or an error occured.
+ *  Return compare-different when target volume can not be read. Might be
+ *  an interrupted volume update and then the target device returns -EIO but
+ *  can be updated.
+ *
+ *  fd_a is source
+ *  fd_b is destination
+ */
+static int compare_files(int fd_a, int fd_b)
+{
+	unsigned char buf_a[COMPARE_BUF_SIZE], buf_b[COMPARE_BUF_SIZE];
+	ssize_t len_a, len_b;
+	int rc;
+
+	for (;;) {
+		len_a = fill_buffer(fd_a, buf_a, sizeof(buf_a));
+		if (len_a == -1) {
+			rc = compare_error;
+			break;
+		}
+		len_b = fill_buffer(fd_b, buf_b, sizeof(buf_b));
+		if (len_b == -1) {
+			rc = compare_different;
+			break;
+		}
+		if (len_a != len_b) {
+			rc = compare_different;
+			break;
+		}
+		if (len_a == 0) {	/* Size on both files equal and EOF */
+			rc = compare_equal;
+			break;
+		}
+		if (memcmp(buf_a, buf_b, len_a) != 0 ) {
+			rc = compare_different;
+			break;
+		}
+	}
+	/* Position both files at the beginning */
+	if (lseek(fd_a, 0, SEEK_SET) == -1 ||
+	   lseek(fd_b, 0, SEEK_SET) == -1)
+		rc = seek_error;
+	return rc;
+}
+
+int vol_get_used_bytes(int vol_fd, unsigned long long *bytes)
+{
+	off_t res;
+
+	res = lseek(vol_fd, 0, SEEK_END);
+	if (res == (off_t)-1)
+		return -1;
+	*bytes = (unsigned long long) res;
+	res = lseek(vol_fd, 0, SEEK_SET);
+	return res == (off_t)-1 ? -1 : 0;
+}
+
+static int copy_files(libubi_t ulib, int fd_in, int fd_out)
+{
+	unsigned char buf_a[COMPARE_BUF_SIZE];
+	ssize_t len_a, len_b;
+	unsigned long long update_size, copied;
+
+	if (vol_get_used_bytes(fd_in, &update_size) == -1 ||
+	    ubi_update_start(ulib, fd_out, update_size) == -1)
+		return update_error;
+	for (copied = 0; copied < update_size; copied += len_b ) {
+		len_a = fill_buffer(fd_in, buf_a, sizeof(buf_a));
+		if (len_a == -1)
+			return read_error;
+		if (len_a == 0)		/* Reach EOF */
+			return 0;
+		len_b = flush_buffer(fd_out, buf_a, len_a);
+		if (len_b != len_a)
+			return write_error;
+	}
+	return 0;
+}
+
+int ubimirror(uint32_t devno, int seqnum, uint32_t *ids, ssize_t ids_size,
+		char *err_buf, size_t err_buf_size)
+{
+	int rc = 0;
+	uint32_t src_id;
+	char path[PATH_MAX];
+	libubi_t ulib;
+	int fd_in = -1, i = 0, fd_out = -1;
+
+	if (ids_size == 0)
+		return 0;
+	else {
+		if ((seqnum < 0) || (seqnum > (ids_size - 1))) {
+			EBUF("volume id %d out of range", seqnum);
+			return EUBIMIRROR_NO_SRC;
+		}
+		src_id = ids[seqnum];
+	}
+
+	ulib = libubi_open();
+	if (ulib == NULL)
+		return ubi_error;
+
+	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, src_id);
+
+	fd_in = open(path, O_RDONLY);
+	if (fd_in == -1) {
+		EBUF("open error source volume %d", ids[i]);
+		rc = open_error;
+		goto err;
+	}
+
+	for (i = 0; i < ids_size; i++) {
+		if (ids[i] == src_id)		/* skip self-mirror */
+			continue;
+
+		snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, ids[i]);
+
+		fd_out = open(path, O_RDWR);
+		if (fd_out < 0){
+			EBUF("open error destination volume %d", ids[i]);
+			rc = open_error;
+			goto err;
+		}
+		rc = compare_files(fd_in, fd_out);
+		if (rc < 0) {
+			EBUF("compare error volume %d and %d", src_id, ids[i]);
+			goto err;
+		} else if (rc == compare_different) {
+			rc = copy_files(ulib, fd_in, fd_out);
+			if (rc != 0) {
+				EBUF("mirror error volume %d to %d", src_id,
+						ids[i]);
+				goto err;
+			}
+		}
+		if ((rc = close(fd_out)) == -1) {
+			EBUF("close error volume %d", ids[i]);
+			rc = close_error;
+			goto err;
+		} else
+			fd_out = -1;
+	}
+err:
+	if (fd_out != -1)
+		close(fd_out);
+	if (fd_in != -1)
+		close(fd_in);
+	if (ulib != NULL)
+		libubi_close(ulib);
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/list.c b/ubi-utils/old-utils/src/list.c
new file mode 100644
index 0000000..6eb716b
--- /dev/null
+++ b/ubi-utils/old-utils/src/list.c
@@ -0,0 +1,149 @@
+/*
+ * 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
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+
+#include "list.h"
+
+list_t
+mk_empty(void)
+{
+	return (list_t) NULL;
+}
+
+int
+is_empty(list_t l)
+{
+	return l == NULL;
+}
+
+info_t
+head(list_t l)
+{
+	assert(!is_empty(l));
+	return l->info;
+}
+
+list_t
+tail(list_t l)
+{
+	assert(!is_empty(l));
+	return l->next;
+}
+
+list_t
+remove_head(list_t l)
+{
+	list_t res;
+	assert(!is_empty(l));
+
+	res = l->next;
+	free(l);
+	return res;
+}
+
+list_t
+cons(info_t e, list_t l)
+{
+	list_t res = malloc(sizeof(*l));
+	if (!res)
+		return NULL;
+	res->info = e;
+	res->next = l;
+
+	return res;
+}
+
+list_t
+prepend_elem(info_t e, list_t l)
+{
+	return cons(e,l);
+}
+
+list_t
+append_elem(info_t e, list_t l)
+{
+	if (is_empty(l)) {
+		return cons(e,l);
+	}
+	l->next = append_elem(e, l->next);
+
+	return l;
+}
+
+list_t
+insert_sorted(cmp_func_t cmp, info_t e, list_t l)
+{
+	if (is_empty(l))
+		return cons(e, l);
+
+	switch (cmp(e, l->info)) {
+	case -1:
+	case  0:
+		return l;
+		break;
+	case  1:
+		l->next = insert_sorted(cmp, e, l);
+		break;
+	default:
+		break;
+	}
+
+	/* never reached */
+	return NULL;
+}
+
+list_t
+remove_all(free_func_t free_func, list_t l)
+{
+	if (is_empty(l))
+		return l;
+	list_t lnext = l->next;
+
+	if (free_func && l->info) {
+		free_func(&(l->info));
+	}
+	free(l);
+
+	return remove_all(free_func, lnext);
+}
+
+
+info_t
+is_in(cmp_func_t cmp, info_t e, list_t l)
+{
+	return
+	(is_empty(l))
+	? NULL
+	: (cmp(e, l->info)) == 0 ? l->info : is_in(cmp, e, l->next);
+}
+
+
+void
+apply(process_func_t process_func, list_t l)
+{
+	list_t ptr;
+	void *i;
+	foreach(i, ptr, l) {
+		process_func(i);
+	}
+}
diff --git a/ubi-utils/old-utils/src/list.h b/ubi-utils/old-utils/src/list.h
new file mode 100644
index 0000000..e8452a2
--- /dev/null
+++ b/ubi-utils/old-utils/src/list.h
@@ -0,0 +1,56 @@
+#ifndef __LIST_H__
+#define __LIST_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: Oliver Lohmann
+ */
+
+#include <stdint.h>
+
+#define foreach(elem, ptr, list)				\
+	for (elem = list != NULL ? (typeof(elem)) head(list)	\
+				 : NULL, ptr = list;		\
+		ptr != NULL;					\
+		ptr = tail(ptr),				\
+		elem = (typeof(elem)) ptr ? head(ptr) : NULL)
+
+typedef struct node* list_t;
+typedef void* info_t;
+typedef int  (*free_func_t)(info_t*);
+typedef int  (*cmp_func_t)(info_t, info_t);
+typedef void (*process_func_t)(info_t);
+
+struct node {
+	list_t next;
+	info_t	info;
+};
+
+list_t mk_empty(void);
+int    is_empty(list_t l);
+info_t is_in(cmp_func_t cmp, info_t e, list_t l);
+info_t head(list_t l);
+list_t tail(list_t l);
+list_t remove_head(list_t l);
+list_t cons(info_t e, list_t l);
+list_t prepend_elem(info_t e, list_t);
+list_t append_elem(info_t e, list_t);
+list_t remove_all(free_func_t free_func, list_t l);
+list_t insert_sorted(cmp_func_t cmp_func, info_t e, list_t l);
+void   apply(process_func_t process_func, list_t l);
+
+#endif /* __LIST_H__ */
diff --git a/ubi-utils/old-utils/src/mkbootenv.c b/ubi-utils/old-utils/src/mkbootenv.c
new file mode 100644
index 0000000..50fc8ac
--- /dev/null
+++ b/ubi-utils/old-utils/src/mkbootenv.c
@@ -0,0 +1,168 @@
+/*
+ * 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
+ *
+ * Create boot-parameter/pdd data from an ASCII-text input file.
+ *
+ * 1.2 Removed argp because we want to use uClibc.
+ * 1.3 Minor cleanup
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <errno.h>
+#include <mtd/ubi-media.h>
+
+#include "config.h"
+#include "bootenv.h"
+#include "error.h"
+
+#define PROGRAM_VERSION "1.3"
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+	"mkbootenv - processes bootenv text files and convertes "
+	"them into a binary format.\n";
+
+static const char copyright [] __attribute__((unused)) =
+	"Copyright (c) International Business Machines Corp., 2006";
+
+static const char *optionsstr =
+"  -c, --copyright          Print copyright informatoin.\n"
+"  -o, --output=<fname>     Write the output data to <output> instead of\n"
+"                           stdout.\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: mkbootenv [-c?V] [-o <output>] [--copyright] [--output=<output>]\n"
+"            [--help] [--usage] [--version] [bootenv-txt-file]\n";
+
+struct option long_options[] = {
+	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
+	{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
+	{ .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}
+};
+
+typedef struct myargs {
+	FILE* fp_in;
+	FILE* fp_out;
+
+	char *arg1;
+	char **options;			/* [STRING...] */
+} myargs;
+
+static int
+parse_opt(int argc, char **argv, myargs *args)
+{
+	while (1) {
+		int key;
+
+		key = getopt_long(argc, argv, "co:?V", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+			case 'c':
+				fprintf(stderr, "%s\n", copyright);
+				exit(0);
+				break;
+			case 'o':
+				args->fp_out = fopen(optarg, "wb");
+				if ((args->fp_out) == NULL) {
+					fprintf(stderr, "Cannot open file %s "
+						"for output\n", optarg);
+					exit(1);
+				}
+				break;
+			case '?': /* help */
+				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);
+		}
+	}
+
+	if (optind < argc) {
+		args->fp_in = fopen(argv[optind++], "rb");
+		if ((args->fp_in) == NULL) {
+			fprintf(stderr,	"Cannot open file %s for input\n",
+				argv[optind]);
+			exit(1);
+		}
+	}
+
+	return 0;
+}
+
+int
+main(int argc, char **argv) {
+	int rc = 0;
+	bootenv_t env;
+
+	myargs args = {
+		.fp_in = stdin,
+		.fp_out = stdout,
+		.arg1 = NULL,
+		.options = NULL,
+	};
+
+	parse_opt(argc, argv, &args);
+
+	rc = bootenv_create(&env);
+	if (rc != 0) {
+		err_msg("Cannot create bootenv handle.");
+		goto err;
+	}
+	rc = bootenv_read_txt(args.fp_in, env);
+	if (rc != 0) {
+		err_msg("Cannot read bootenv from input file.");
+		goto err;
+	}
+	rc = bootenv_write(args.fp_out, env);
+	if (rc != 0) {
+		err_msg("Cannot write bootenv to output file.");
+		goto err;
+	}
+
+	if (args.fp_in != stdin) {
+		fclose(args.fp_in);
+	}
+	if (args.fp_out != stdout) {
+		fclose(args.fp_out);
+	}
+
+err:
+	bootenv_destroy(&env);
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/nand2bin.c b/ubi-utils/old-utils/src/nand2bin.c
new file mode 100644
index 0000000..93ba29f
--- /dev/null
+++ b/ubi-utils/old-utils/src/nand2bin.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006, 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Frank Haverkamp
+ *
+ * An utility to decompose NAND images and strip OOB off. Not yet finished ...
+ *
+ * 1.2 Removed argp because we want to use uClibc.
+ * 1.3 Minor cleanup
+ * 1.4 Fixed OOB output file
+ * 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.
+ */
+
+#include <config.h>
+#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/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "config.h"
+#include "nandecc.h"
+
+#define PROGRAM_VERSION "1.6"
+
+#define MAXPATH		1024
+#define MIN(x,y)	((x)<(y)?(x):(y))
+
+struct args {
+	const char *oob_file;
+	const char *output_file;
+	size_t pagesize;
+	size_t blocksize;
+	int split_blocks;
+	size_t in_len;		/* size of input file */
+	int correct_ecc;
+
+	/* special stuff needed to get additional arguments */
+	char *arg1;
+	char **options;		/* [STRING...] */
+};
+
+static struct args myargs = {
+	.output_file = "data.bin",
+	.oob_file = "oob.bin",
+	.pagesize = 2048,
+	.blocksize = 128 * 1024,
+	.in_len = 0,
+	.split_blocks = 0,
+	.correct_ecc = 0,
+	.arg1 = NULL,
+	.options = NULL,
+};
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+	"nand2bin - split data and OOB.\n";
+
+static const char *optionsstr =
+"  -o, --output=<output>      Data output file\n"
+"  -O, --oob=<oob>            OOB output file\n"
+"  -p, --pagesize=<pagesize>  NAND pagesize\n"
+"  -b, --blocksize=<blocksize> NAND blocksize\n"
+"  -s, --split-blocks         generate binaries for each block\n"
+"  -e, --correct-ecc          Correct data according to ECC info\n"
+"  -v, --verbose              verbose output\n"
+"  -?, --help                 Give this help list\n"
+"      --usage                Give a short usage message\n";
+
+static const char *usage =
+"Usage: nand2bin [-?] [-o <output>] [-O <oob>] [-p <pagesize>]\n"
+"          [--output=<output>] [--oob=<oob>] [--pagesize=<pagesize>] [--help]\n"
+"          [--usage] input.mif\n";
+
+static int verbose = 0;
+
+static struct option long_options[] = {
+	{ .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' },
+	{ .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'b' },
+	{ .name = "split-blocks", .has_arg = 0, .flag = NULL, .val = 's' },
+	{ .name = "correct-ecc", .has_arg = 0, .flag = NULL, .val = 'e' },
+	{ .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "help", .has_arg = 0, .flag = NULL, .val = '?' },
+	{ .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 },
+	{ NULL, 0, NULL, 0}
+};
+
+/*
+ * str_to_num - Convert string into number and cope with endings like
+ *              k, K, kib, KiB for kilobyte
+ *              m, M, mib, MiB for megabyte
+ */
+static uint32_t str_to_num(char *str)
+{
+	char *s = str;
+	ulong num = strtoul(s, &s, 0);
+
+	if (*s != '\0') {
+		if (strcmp(s, "KiB") == 0)
+			num *= 1024;
+		else if (strcmp(s, "MiB") == 0)
+			num *= 1024*1024;
+		else {
+			fprintf(stderr, "WARNING: Wrong number format "
+				"\"%s\", check your paramters!\n", str);
+		}
+	}
+	return num;
+}
+
+/*
+ * @brief Parse the arguments passed into the test case.
+ *
+ * @param argc           The number of arguments
+ * @param argv           The argument list
+ * @param args           Pointer to program args structure
+ *
+ * @return error
+ *
+ */
+static int parse_opt(int argc, char **argv, struct args *args)
+{
+	while (1) {
+		int key;
+
+		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 'o': /* --output=<output.bin> */
+			args->output_file = optarg;
+			break;
+
+		case 'O': /* --oob=<oob.bin> */
+			args->oob_file = optarg;
+			break;
+
+		case '?': /* help */
+			printf("Usage: nand2bin [OPTION...] input.mif\n");
+			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);
+		}
+	}
+
+	if (optind < argc)
+		args->arg1 = argv[optind++];
+
+	return 0;
+}
+
+static int calc_oobsize(size_t pagesize)
+{
+	switch (pagesize) {
+	case 512:  return 16;
+	case 2048: return 64;
+	default:
+		exit(EXIT_FAILURE);
+	}
+	return 0;
+}
+
+static inline void hexdump(FILE *fp, const uint8_t *buf, ssize_t size)
+{
+	int k;
+
+	for (k = 0; k < size; k++) {
+		fprintf(fp, "%02x ", buf[k]);
+		if ((k & 15) == 15)
+			fprintf(fp, "\n");
+	}
+}
+
+static int process_page(uint8_t* buf, uint8_t *oobbuf, size_t pagesize)
+{
+	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)
+{
+	int read, rc, page = 0;
+	size_t oobsize = calc_oobsize(args->pagesize);
+	uint8_t *buf = malloc(args->pagesize);
+	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 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)
+		exit(EXIT_FAILURE);
+	if (!oob)
+		exit(EXIT_FAILURE);
+	if (!calc_oob)
+		exit(EXIT_FAILURE);
+	if (!calc_buf)
+		exit(EXIT_FAILURE);
+
+	while (!feof(in_fp)) {
+		/* read page by page */
+		read = fread(buf, 1, args->pagesize, in_fp);
+		if (ferror(in_fp)) {
+			fprintf(stderr, "I/O Error.");
+			exit(EXIT_FAILURE);
+		}
+		if (read != (ssize_t)args->pagesize)
+			break;
+
+		read = fread(oob, 1, oobsize, in_fp);
+		if (ferror(in_fp)) {
+			fprintf(stderr, "I/O Error.");
+			exit(EXIT_FAILURE);
+		}
+
+		page_buf = buf;	/* default is unmodified data */
+
+		if ((page == 0 || page == 1) && (oob[badpos] != 0xff)) {
+			if (verbose)
+				printf("Block %d is bad\n",
+				       page / pages_per_block);
+			goto write_data;
+		}
+		if (args->correct_ecc)
+			page_buf = calc_buf;
+
+		process_page(buf, calc_oob, args->pagesize);
+		memcpy(calc_buf, buf, args->pagesize);
+
+		/*
+		 * 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, oobsize);
+
+			printf("Calculated OOB Data:\n");
+			hexdump(stdout, calc_oob, oobsize);
+		}
+
+		/* Do correction on subpage base */
+		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",
+					page / pages_per_block,
+					page % pages_per_block, i / 256);
+			else if (rc > 0)
+				fprintf(stdout, "Correctable ECC error at "
+					"block %d page %d/%d\n",
+					page / pages_per_block,
+					page % pages_per_block, i / 256);
+		}
+
+	write_data:
+		rc = fwrite(page_buf, 1, args->pagesize, bin_fp);
+		if (ferror(bin_fp)) {
+			fprintf(stderr, "I/O Error.");
+			exit(EXIT_FAILURE);
+		}
+		rc = fwrite(oob, 1, oobsize, oob_fp);
+		if (ferror(bin_fp)) {
+			fprintf(stderr, "I/O Error.");
+			exit(EXIT_FAILURE);
+		}
+
+		page++;
+	}
+	free(calc_buf);
+	free(calc_oob);
+	free(oob);
+	free(buf);
+	return 0;
+}
+
+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 + oobsize);
+	int blocks = args->in_len / block_len;
+	char bname[256] = { 0, };
+	int badpos = bad_marker_offs_in_oob(args->pagesize);
+	int bad_blocks = 0, i, bad_block = 0;
+	ssize_t rc;
+	FILE *b;
+
+	buf = malloc(block_len);
+	if (!buf) {
+		perror("Not enough memory");
+		exit(EXIT_FAILURE);
+	}
+
+	for (i = 0; i < blocks; i++) {
+		rc = fread(buf, 1, block_len, in_fp);
+		if (rc != block_len) {
+			fprintf(stderr, "cannot read enough data!\n");
+			exit(EXIT_FAILURE);
+		}
+
+		/* do block analysis */
+		bad_block = 0;
+		if ((buf[args->pagesize + 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, oobsize);
+			printf("--\n");
+			hexdump(stdout, buf + 2 * args->pagesize +
+				oobsize, oobsize);
+		}
+
+		/* write complete block out */
+		snprintf(bname, sizeof(bname) - 1, "%s.%d", args->arg1, i);
+		b = fopen(bname, "w+");
+		if (!b) {
+			perror("Cannot open file");
+			exit(EXIT_FAILURE);
+		}
+		rc = fwrite(buf, 1, block_len, b);
+		if (rc != block_len) {
+			fprintf(stderr, "could not write all data!\n");
+			exit(EXIT_FAILURE);
+		}
+		fclose(b);
+	}
+
+	free(buf);
+	if (bad_blocks || verbose)
+		fprintf(stderr, "%d blocks, %d bad blocks\n",
+			blocks, bad_blocks);
+	return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+	FILE *in, *bin = NULL, *oob = NULL;
+	struct stat file_info;
+
+	parse_opt(argc, argv, &myargs);
+
+	if (!myargs.arg1) {
+		fprintf(stderr, "Please specify input file!\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (stat(myargs.arg1, &file_info) != 0) {
+		perror("Cannot fetch file size from input file.\n");
+		exit(EXIT_FAILURE);
+	}
+	myargs.in_len = file_info.st_size;
+
+	in = fopen(myargs.arg1, "r");
+	if (!in) {
+		perror("Cannot open file");
+		exit(EXIT_FAILURE);
+	}
+
+	if (myargs.split_blocks) {
+		split_blocks(&myargs, in);
+		goto out;
+	}
+
+	bin = fopen(myargs.output_file, "w+");
+	if (!bin) {
+		perror("Cannot open file");
+		exit(EXIT_FAILURE);
+	}
+	oob = fopen(myargs.oob_file, "w+");
+	if (!oob) {
+		perror("Cannot open file");
+		exit(EXIT_FAILURE);
+	}
+	decompose_image(&myargs, in, bin, oob);
+
+ out:
+	if (in)	 fclose(in);
+	if (bin) fclose(bin);
+	if (oob) fclose(oob);
+	exit(EXIT_SUCCESS);
+}
diff --git a/ubi-utils/old-utils/src/nandcorr.c b/ubi-utils/old-utils/src/nandcorr.c
new file mode 100644
index 0000000..caa07e2
--- /dev/null
+++ b/ubi-utils/old-utils/src/nandcorr.c
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+/*
+ * ECC algorithm for NAND FLASH. Detects and corrects 1 bit errors in
+ * a 256 bytes of data.
+ *
+ * Reimplement by Thomas Gleixner after staring long enough at the
+ * mess in drivers/mtd/nand/nandecc.c
+ *
+ */
+
+#include "nandecc.h"
+
+static int countbits(uint32_t byte)
+{
+	int res = 0;
+
+	for (;byte; byte >>= 1)
+		res += byte & 0x01;
+	return res;
+}
+
+/**
+ * @dat:       data which should be corrected
+ * @read_ecc:  ecc information read from flash
+ * @calc_ecc:  calculated ecc information from the data
+ * @return:    number of corrected bytes
+ *             or -1 when no correction is possible
+ */
+int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc,
+		      const uint8_t *calc_ecc)
+{
+	uint8_t s0, s1, s2;
+
+	/*
+	 * Do error detection
+	 *
+	 * Be careful, the index magic is due to a pointer to a
+	 * uint32_t.
+	 */
+	s0 = calc_ecc[0] ^ read_ecc[0];
+	s1 = calc_ecc[1] ^ read_ecc[1];
+	s2 = calc_ecc[2] ^ read_ecc[2];
+
+	if ((s0 | s1 | s2) == 0)
+		return 0;
+
+	/* Check for a single bit error */
+	if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
+	    ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
+	    ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
+
+		uint32_t byteoffs, bitnum;
+
+		byteoffs = (s1 << 0) & 0x80;
+		byteoffs |= (s1 << 1) & 0x40;
+		byteoffs |= (s1 << 2) & 0x20;
+		byteoffs |= (s1 << 3) & 0x10;
+
+		byteoffs |= (s0 >> 4) & 0x08;
+		byteoffs |= (s0 >> 3) & 0x04;
+		byteoffs |= (s0 >> 2) & 0x02;
+		byteoffs |= (s0 >> 1) & 0x01;
+
+		bitnum = (s2 >> 5) & 0x04;
+		bitnum |= (s2 >> 4) & 0x02;
+		bitnum |= (s2 >> 3) & 0x01;
+
+		dat[byteoffs] ^= (1 << bitnum);
+
+		return 1;
+	}
+
+	if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
+		return 1;
+
+	return -1;
+}
+
diff --git a/ubi-utils/old-utils/src/nandecc.c b/ubi-utils/old-utils/src/nandecc.c
new file mode 100644
index 0000000..71660ef
--- /dev/null
+++ b/ubi-utils/old-utils/src/nandecc.c
@@ -0,0 +1,159 @@
+/*
+ * This file contains an ECC algorithm from Toshiba that detects and
+ * corrects 1 bit errors in a 256 byte block of data.
+ *
+ * drivers/mtd/nand/nand_ecc.c
+ *
+ * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
+ *			   Toshiba America Electronics Components, Inc.
+ *
+ * This file 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 or (at your option) any
+ * later version.
+ *
+ * This file 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 file; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * As a special exception, if other files instantiate templates or use
+ * macros or inline functions from these files, or you compile these
+ * files and link them with other works to produce a work based on these
+ * files, these files do not by themselves cause the resulting work to be
+ * covered by the GNU General Public License. However the source code for
+ * these files must still be made available in accordance with section (3)
+ * of the GNU General Public License.
+ *
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include "nandecc.h"
+
+/*
+ * Pre-calculated 256-way 1 byte column parity
+ */
+static const uint8_t nand_ecc_precalc_table[] = {
+	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+	0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+	0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+	0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+	0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+	0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+	0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+	0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+	0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+	0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+	0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+	0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+	0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+	0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+	0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+	0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+	0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
+};
+
+/**
+ * nand_trans_result - [GENERIC] create non-inverted ECC
+ * @reg2:	line parity reg 2
+ * @reg3:	line parity reg 3
+ * @ecc_code:	ecc
+ *
+ * Creates non-inverted ECC code from line parity
+ */
+static void nand_trans_result(uint8_t reg2, uint8_t reg3,
+	uint8_t *ecc_code)
+{
+	uint8_t a, b, i, tmp1, tmp2;
+
+	/* Initialize variables */
+	a = b = 0x80;
+	tmp1 = tmp2 = 0;
+
+	/* Calculate first ECC byte */
+	for (i = 0; i < 4; i++) {
+		if (reg3 & a)		/* LP15,13,11,9 --> ecc_code[0] */
+			tmp1 |= b;
+		b >>= 1;
+		if (reg2 & a)		/* LP14,12,10,8 --> ecc_code[0] */
+			tmp1 |= b;
+		b >>= 1;
+		a >>= 1;
+	}
+
+	/* Calculate second ECC byte */
+	b = 0x80;
+	for (i = 0; i < 4; i++) {
+		if (reg3 & a)		/* LP7,5,3,1 --> ecc_code[1] */
+			tmp2 |= b;
+		b >>= 1;
+		if (reg2 & a)		/* LP6,4,2,0 --> ecc_code[1] */
+			tmp2 |= b;
+		b >>= 1;
+		a >>= 1;
+	}
+
+	/* Store two of the ECC bytes */
+	ecc_code[1] = tmp1;
+	ecc_code[0] = tmp2;
+}
+
+/**
+ * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for
+ * 256 byte block
+ *
+ * @dat:	raw data
+ * @ecc_code:	buffer for ECC
+ */
+int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code)
+{
+	uint8_t idx, reg1, reg2, reg3;
+	int j;
+
+	/* Initialize variables */
+	reg1 = reg2 = reg3 = 0;
+	ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
+
+	/* Build up column parity */
+	for(j = 0; j < 256; j++) {
+
+		/* Get CP0 - CP5 from table */
+		idx = nand_ecc_precalc_table[dat[j]];
+		reg1 ^= (idx & 0x3f);
+
+		/* All bit XOR = 1 ? */
+		if (idx & 0x40) {
+			reg3 ^= (uint8_t) j;
+			reg2 ^= ~((uint8_t) j);
+		}
+	}
+
+	/* Create non-inverted ECC code from line parity */
+	nand_trans_result(reg2, reg3, ecc_code);
+
+	/* Calculate final ECC code */
+	ecc_code[0] = ~ecc_code[0];
+	ecc_code[1] = ~ecc_code[1];
+	ecc_code[2] = ((~reg1) << 2) | 0x03;
+	return 0;
+}
diff --git a/ubi-utils/old-utils/src/nandecc.h b/ubi-utils/old-utils/src/nandecc.h
new file mode 100644
index 0000000..bcf1982
--- /dev/null
+++ b/ubi-utils/old-utils/src/nandecc.h
@@ -0,0 +1,29 @@
+#ifndef _NAND_ECC_H
+#define _NAND_ECC_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.
+ *
+ * NAND ecc functions
+ */
+
+#include <stdint.h>
+
+int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code);
+int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc,
+		      const uint8_t *calc_ecc);
+
+#endif
diff --git a/ubi-utils/old-utils/src/pddcustomize.c b/ubi-utils/old-utils/src/pddcustomize.c
new file mode 100644
index 0000000..1eb9b9a
--- /dev/null
+++ b/ubi-utils/old-utils/src/pddcustomize.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2008
+ *
+ * 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
+ *
+ * PDD (platform description data) contains a set of system specific
+ * boot-parameters. Some of those parameters need to be handled
+ * special on updates, e.g. the MAC addresses. They must also be kept
+ * if the system is updated and one must be able to modify them when
+ * the system has booted the first time. This tool is intended to do
+ * PDD modification.
+ *
+ * 1.3 Removed argp because we want to use uClibc.
+ * 1.4 Minor cleanups
+ * 1.5 Migrated to new libubi
+ * 1.6 Fixed broken volume update
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <mtd/ubi-media.h>
+
+#include "config.h"
+#include "bootenv.h"
+#include "error.h"
+#include "example_ubi.h"
+#include "libubi.h"
+#include "ubimirror.h"
+
+#define PROGRAM_VERSION "1.6"
+
+#define DEFAULT_DEV_PATTERN    "/dev/ubi%d"
+#define DEFAULT_VOL_PATTERN    "/dev/ubi%d_%d"
+
+typedef enum action_t {
+	ACT_NORMAL   = 0,
+	ACT_LIST,
+	ACT_ARGP_ABORT,
+	ACT_ARGP_ERR,
+} action_t;
+
+#define ABORT_ARGP do {			\
+	args->action = ACT_ARGP_ABORT;	\
+} while (0)
+
+#define ERR_ARGP do {			\
+	args->action = ACT_ARGP_ERR;	\
+} while (0)
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+	"pddcustomize - customize bootenv and pdd values.\n";
+
+static const char *optionsstr =
+"  -b, --both                 Mirror updated PDD to redundand copy.\n"
+"  -c, --copyright            Print copyright information.\n"
+"  -i, --input=<input>        Binary input file. For debug purposes.\n"
+"  -l, --list                 List card bootenv/pdd values.\n"
+"  -o, --output=<output>      Binary output file. For debug purposes.\n"
+"  -s, --side=<seqnum>        The side/seqnum to update.\n"
+"  -x, --host                 use x86 platform for debugging.\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: pddcustomize [-bclx?V] [-i <input>] [-o <output>] [-s <seqnum>]\n"
+"           [--both] [--copyright] [--input=<input>] [--list]\n"
+"           [--output=<output>] [--side=<seqnum>] [--host] [--help] [--usage]\n"
+"           [--version] [key=value] [...]\n";
+
+struct option long_options[] = {
+	{ .name = "both", .has_arg = 0, .flag = NULL, .val = 'b' },
+	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
+	{ .name = "input", .has_arg = 1, .flag = NULL, .val = 'i' },
+	{ .name = "list", .has_arg = 0, .flag = NULL, .val = 'l' },
+	{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
+	{ .name = "side", .has_arg = 1, .flag = NULL, .val = 's' },
+	{ .name = "host", .has_arg = 0, .flag = NULL, .val = 'x' },
+	{ .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}
+};
+
+static const char copyright [] __attribute__((unused)) =
+	"Copyright IBM Corp 2006";
+
+typedef struct myargs {
+	action_t action;
+	const char* file_in;
+	const char* file_out;
+	int both;
+	int side;
+	int x86;		/* X86 host, use files for testing */
+	bootenv_t env_in;
+
+	char *arg1;
+	char **options;		/* [STRING...] */
+} myargs;
+
+static int
+get_update_side(const char* str)
+{
+	uint32_t i = strtoul(str, NULL, 0);
+
+	if ((i != 0) && (i != 1)) {
+		return -1;
+	}
+
+	return i;
+}
+
+static int
+extract_pair(bootenv_t env, const char* str)
+{
+	int rc = 0;
+	char* key;
+	char* val;
+
+	key = strdup(str);
+	if (key == NULL)
+		return -ENOMEM;
+
+	val = strstr(key, "=");
+	if (val == NULL) {
+		err_msg("Wrong argument: %s\n"
+			"Expecting key=value pair.\n", str);
+		rc = -1;
+		goto err;
+	}
+
+	*val = '\0'; /* split strings */
+	val++;
+	rc = bootenv_set(env, key, val);
+
+err:
+	free(key);
+	return rc;
+}
+
+static int
+parse_opt(int argc, char **argv, myargs *args)
+{
+	int rc = 0;
+
+	while (1) {
+		int key;
+
+		key = getopt_long(argc, argv, "clbxs:i:o:?V",
+				  long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+			case 'c':
+				err_msg("%s\n", copyright);
+				ABORT_ARGP;
+				break;
+			case 'l':
+				args->action = ACT_LIST;
+				break;
+			case 'b':
+				args->both = 1;
+				break;
+			case 'x':
+				args->x86 = 1;
+				break;
+			case 's':
+				args->side = get_update_side(optarg);
+				if (args->side < 0) {
+					err_msg("Unsupported seqnum: %d.\n"
+						"Supported seqnums are "
+						"'0' and '1'\n",
+						args->side, optarg);
+					ERR_ARGP;
+				}
+				break;
+			case 'i':
+				args->file_in = optarg;
+				break;
+			case 'o':
+				args->file_out = optarg;
+				break;
+			case '?': /* help */
+				err_msg("Usage: pddcustomize [OPTION...] "
+					"[key=value] [...]");
+				err_msg("%s", doc);
+				err_msg("%s", optionsstr);
+				err_msg("\nReport bugs to %s",
+					PACKAGE_BUGREPORT);
+				exit(0);
+				break;
+			case 'V':
+				err_msg("%s", PROGRAM_VERSION);
+				exit(0);
+				break;
+			default:
+				err_msg("%s", usage);
+				exit(-1);
+		}
+	}
+
+	if (optind < argc) {
+		rc = extract_pair(args->env_in, argv[optind++]);
+		if (rc != 0)
+			ERR_ARGP;
+	}
+
+	return 0;
+}
+
+static int
+list_bootenv(bootenv_t env)
+{
+	int rc = 0;
+	rc = bootenv_write_txt(stdout, env);
+	if (rc != 0) {
+		err_msg("Cannot list bootenv/pdd. rc: %d\n", rc);
+		goto err;
+	}
+err:
+	return rc;
+}
+
+static int
+process_key_value(bootenv_t env_in, bootenv_t env)
+{
+	int rc = 0;
+	size_t size, i;
+	const char* tmp;
+	const char** key_vec = NULL;
+
+	rc = bootenv_get_key_vector(env_in, &size, 0, &key_vec);
+	if (rc != 0)
+		goto err;
+
+	for (i = 0; i < size; i++) {
+		rc = bootenv_get(env_in, key_vec[i], &tmp);
+		if (rc != 0) {
+			err_msg("Cannot read value to input key: %s. rc: %d\n",
+					key_vec[i], rc);
+			goto err;
+		}
+		rc = bootenv_set(env, key_vec[i], tmp);
+		if (rc != 0) {
+			err_msg("Cannot set value key: %s. rc: %d\n",
+					key_vec[i], rc);
+			goto err;
+		}
+	}
+
+err:
+	if (key_vec != NULL)
+		free(key_vec);
+	return rc;
+}
+
+static int
+read_bootenv(const char* file, bootenv_t env)
+{
+	int rc = 0;
+	FILE* fp_in = NULL;
+
+	fp_in = fopen(file, "rb");
+	if (fp_in == NULL) {
+		err_msg("Cannot open file: %s\n", file);
+		return -EIO;
+	}
+
+	rc = bootenv_read(fp_in, env, BOOTENV_MAXSIZE);
+	if (rc != 0) {
+		err_msg("Cannot read bootenv from file %s. rc: %d\n",
+			file, rc);
+		goto err;
+	}
+
+err:
+	fclose(fp_in);
+	return rc;
+}
+
+/*
+ * Read bootenv from ubi volume
+ */
+static int
+ubi_read_bootenv(uint32_t devno, uint32_t id, bootenv_t env)
+{
+	libubi_t ulib;
+	int rc = 0;
+	char path[PATH_MAX];
+	FILE* fp_in = NULL;
+
+	ulib = libubi_open();
+	if (ulib == NULL) {
+		err_msg("Cannot allocate ubi structure\n");
+		return -1;
+	}
+
+	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
+
+	fp_in = fopen(path, "r");
+	if (fp_in == NULL) {
+		err_msg("Cannot open volume:%d number:%d\n", devno, id);
+		goto err;
+	}
+
+	rc = bootenv_read(fp_in, env, BOOTENV_MAXSIZE);
+	if (rc != 0) {
+		err_msg("Cannot read volume:%d number:%d\n", devno, id);
+		goto err;
+	}
+
+err:
+	if (fp_in)
+		fclose(fp_in);
+	libubi_close(ulib);
+	return rc;
+}
+
+static int
+write_bootenv(const char* file, bootenv_t env)
+{
+	int rc = 0;
+	FILE* fp_out;
+
+	fp_out = fopen(file, "wb");
+	if (fp_out == NULL) {
+		err_msg("Cannot open file: %s\n", file);
+		return -EIO;
+	}
+
+	rc = bootenv_write(fp_out, env);
+	if (rc != 0) {
+		err_msg("Cannot write bootenv to file %s. rc: %d\n", file, rc);
+		goto err;
+	}
+
+err:
+	fclose(fp_out);
+	return rc;
+}
+
+/*
+ * Read bootenv from ubi volume
+ */
+static int
+ubi_write_bootenv(uint32_t devno, uint32_t id, bootenv_t env)
+{
+	libubi_t ulib;
+	int rc = 0;
+	char path[PATH_MAX];
+	FILE* fp_out = NULL;
+	size_t nbytes;
+
+	rc = bootenv_size(env, &nbytes);
+	if (rc) {
+		err_msg("Cannot determine size of bootenv structure\n");
+		return rc;
+	}
+	ulib = libubi_open();
+	if (ulib == NULL) {
+		err_msg("Cannot allocate ubi structure\n");
+		return rc;
+	}
+
+	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
+
+	fp_out = fopen(path, "r+");
+	if (fp_out == NULL) {
+		err_msg("Cannot fopen volume:%d number:%d\n", devno, id);
+		rc = -EBADF;
+		goto err;
+	}
+
+	rc = ubi_update_start(ulib, fileno(fp_out), nbytes);
+	if (rc != 0) {
+		err_msg("Cannot start update for %s\n", path);
+		goto err;
+	}
+
+	rc = bootenv_write(fp_out, env);
+	if (rc != 0) {
+		err_msg("Cannot write bootenv to volume %d number:%d\n",
+			devno, id);
+		goto err;
+	}
+err:
+	if( fp_out )
+		fclose(fp_out);
+	libubi_close(ulib);
+	return rc;
+}
+
+static int
+do_mirror(int volno)
+{
+	char errbuf[1024];
+	uint32_t ids[2];
+	int rc;
+	int src_volno_idx = 0;
+
+	ids[0] = EXAMPLE_BOOTENV_VOL_ID_1;
+	ids[1] = EXAMPLE_BOOTENV_VOL_ID_2;
+
+	if (volno == EXAMPLE_BOOTENV_VOL_ID_2)
+		src_volno_idx = 1;
+
+	rc = ubimirror(EXAMPLE_UBI_DEVICE, src_volno_idx, ids, 2, errbuf,
+		       sizeof errbuf);
+	if( rc )
+		err_msg(errbuf);
+	return rc;
+}
+
+int
+main(int argc, char **argv) {
+	int rc = 0;
+	bootenv_t env = NULL;
+	uint32_t boot_volno;
+	myargs args = {
+		.action = ACT_NORMAL,
+		.file_in  = NULL,
+		.file_out = NULL,
+		.side = -1,
+		.x86 = 0,
+		.both = 0,
+		.env_in = NULL,
+
+		.arg1 = NULL,
+		.options = NULL,
+	};
+
+	rc = bootenv_create(&env);
+	if (rc != 0) {
+		err_msg("Cannot create bootenv handle. rc: %d", rc);
+		goto err;
+	}
+
+	rc = bootenv_create(&(args.env_in));
+	if (rc != 0) {
+		err_msg("Cannot create bootenv handle. rc: %d", rc);
+		goto err;
+	}
+
+	parse_opt(argc, argv, &args);
+	if (args.action == ACT_ARGP_ERR) {
+		rc = -1;
+		goto err;
+	}
+	if (args.action == ACT_ARGP_ABORT) {
+		rc = 0;
+		goto out;
+	}
+
+	if ((args.side == 0) || (args.side == -1))
+		boot_volno = EXAMPLE_BOOTENV_VOL_ID_1;
+	else
+		boot_volno = EXAMPLE_BOOTENV_VOL_ID_2;
+
+	if( args.x86 )
+		rc = read_bootenv(args.file_in, env);
+	else
+		rc = ubi_read_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env);
+	if (rc != 0) {
+		goto err;
+	}
+
+	if (args.action == ACT_LIST) {
+		rc = list_bootenv(env);
+		if (rc != 0) {
+			goto err;
+		}
+		goto out;
+	}
+
+	rc = process_key_value(args.env_in, env);
+	if (rc != 0) {
+		goto err;
+	}
+
+	if( args.x86 )
+		rc = write_bootenv(args.file_in, env);
+	else
+		rc = ubi_write_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env);
+	if (rc != 0)
+		goto err;
+
+	if( args.both )		/* No side specified, update both */
+		rc = do_mirror(boot_volno);
+
+ out:
+ err:
+	bootenv_destroy(&env);
+	bootenv_destroy(&(args.env_in));
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/peb.c b/ubi-utils/old-utils/src/peb.c
new file mode 100644
index 0000000..08b770f
--- /dev/null
+++ b/ubi-utils/old-utils/src/peb.c
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "peb.h"
+
+int
+peb_cmp(peb_t eb_1, peb_t eb_2)
+{
+	assert(eb_1);
+	assert(eb_2);
+
+	return eb_1->num == eb_2->num ? 0
+		: eb_1->num > eb_2->num ? 1 : -1;
+}
+
+int
+peb_new(uint32_t eb_num, uint32_t eb_size, peb_t *peb)
+{
+	int rc = 0;
+
+	peb_t res = (peb_t) malloc(sizeof(struct peb));
+	if (!res) {
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	res->num  = eb_num;
+	res->size = eb_size;
+	res->data = (uint8_t*) malloc(res->size * sizeof(uint8_t));
+	if (!res->data) {
+		rc = -ENOMEM;
+		goto err;
+	}
+	memset(res->data, 0xff, res->size);
+
+	*peb = res;
+	return 0;
+err:
+	if (res) {
+		if (res->data)
+			free(res->data);
+		free(res);
+	}
+	*peb = NULL;
+	return rc;
+}
+
+int
+peb_fill(peb_t peb, uint8_t* buf, size_t buf_size)
+{
+	if (!peb)
+		return -EINVAL;
+
+	if (buf_size > peb->size)
+		return -EINVAL;
+
+	memcpy(peb->data, buf, buf_size);
+	return 0;
+}
+
+int
+peb_write(FILE* fp_out, peb_t peb)
+{
+	size_t written = 0;
+
+	if (peb == NULL)
+		return -EINVAL;
+
+	written = fwrite(peb->data, 1, peb->size, fp_out);
+
+	if (written != peb->size)
+		return -EIO;
+
+	return 0;
+}
+
+int
+peb_free(peb_t* peb)
+{
+	peb_t tmp = *peb;
+	if (tmp) {
+		if (tmp->data)
+			free(tmp->data);
+		free(tmp);
+	}
+	*peb = NULL;
+
+	return 0;
+}
+
+void peb_dump(FILE* fp_out, peb_t peb)
+{
+	fprintf(fp_out, "num: %08d\tsize: 0x%08x\n", peb->num, peb->size);
+}
diff --git a/ubi-utils/old-utils/src/peb.h b/ubi-utils/old-utils/src/peb.h
new file mode 100644
index 0000000..246bce8
--- /dev/null
+++ b/ubi-utils/old-utils/src/peb.h
@@ -0,0 +1,41 @@
+#ifndef __RAW_BLOCK_H__
+#define __RAW_BLOCK_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: Oliver Lohmann
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+typedef struct peb *peb_t;
+struct peb {
+	uint32_t num;		/* Physical eraseblock number
+				 * in the RAW file. */
+	uint32_t size;		/* Data Size (equals physical
+				 * erase block size) */
+	uint8_t* data;		/* Data buffer */
+};
+
+int  peb_new(uint32_t peb_num, uint32_t peb_size, peb_t* peb);
+int  peb_free(peb_t* peb);
+int  peb_cmp(peb_t peb_1, peb_t peb_2);
+int  peb_write(FILE* fp_out, peb_t peb);
+void peb_dump(FILE* fp_out, peb_t peb);
+
+#endif /* __RAW_BLOCK_H__ */
diff --git a/ubi-utils/old-utils/src/pfi.c b/ubi-utils/old-utils/src/pfi.c
new file mode 100644
index 0000000..fa835e2
--- /dev/null
+++ b/ubi-utils/old-utils/src/pfi.c
@@ -0,0 +1,458 @@
+/*
+ * 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.
+ */
+
+/*
+ * @file pfi.c
+ *
+ * @author Oliver Lohmann
+ *	   Andreas Arnez
+ *	   Joern Engel
+ *	   Frank Haverkamp
+ *
+ * @brief libpfi holds all code to create and process pfi files.
+ *
+ * <oliloh@de.ibm.com> Wed Feb	8 11:38:22 CET 2006: Initial creation.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include "pfi.h"
+
+#define PFI_MAGIC     "PFI!\n"
+#define PFI_DATA      "DATA\n" /* The same size as PFI_MAGIC */
+#define PFI_MAGIC_LEN 5
+
+static const char copyright [] __attribute__((unused)) =
+	"Copyright (c) International Business Machines Corp., 2006";
+
+enum key_id {
+	/* version 1 */
+	key_version,	      /* must be index position 0! */
+	key_mode,
+	key_size,
+	key_crc,
+	key_label,
+	key_flags,
+	key_ubi_ids,
+	key_ubi_size,
+	key_ubi_type,
+	key_ubi_names,
+	key_ubi_alignment,
+	key_raw_starts,
+	key_raw_total_size,
+	num_keys,
+};
+
+struct pfi_header {
+	char defined[num_keys];	 /* reserve all possible keys even if
+				    version does not require this. */
+	int mode_no;		 /* current mode no. -> can only increase */
+	union {
+		char *str;
+		uint32_t num;
+	} value[num_keys];
+};
+
+
+#define PFI_MANDATORY	    0x0001
+#define PFI_STRING	    0x0002
+#define PFI_LISTVALUE	    0x0004	/* comma seperated list of nums */
+#define PFI_MANDATORY_UBI   0x0008
+#define PFI_MANDATORY_RAW   0x0010
+
+struct key_descriptor {
+	enum key_id id;
+	const char *name;
+	uint32_t flags;
+};
+
+static const struct key_descriptor key_desc_v1[] = {
+	{ key_version, "version", PFI_MANDATORY },
+	{ key_mode, "mode", PFI_MANDATORY | PFI_STRING },
+	{ key_size, "size", PFI_MANDATORY },
+	{ key_crc, "crc", PFI_MANDATORY },
+	{ key_label, "label", PFI_MANDATORY | PFI_STRING },
+	{ key_flags, "flags", PFI_MANDATORY },
+	{ key_ubi_ids, "ubi_ids", PFI_MANDATORY_UBI | PFI_STRING },
+	{ key_ubi_size, "ubi_size", PFI_MANDATORY_UBI },
+	{ key_ubi_type, "ubi_type", PFI_MANDATORY_UBI | PFI_STRING },
+	{ key_ubi_names, "ubi_names", PFI_MANDATORY_UBI | PFI_STRING },
+	{ key_ubi_alignment, "ubi_alignment", PFI_MANDATORY_UBI },
+	{ key_raw_starts, "raw_starts", PFI_MANDATORY_RAW | PFI_STRING },
+	{ key_raw_total_size, "raw_total_size", PFI_MANDATORY_RAW },
+};
+
+static const struct key_descriptor *key_descriptors[] = {
+	NULL,
+	key_desc_v1,					   /* version 1 */
+};
+
+static const int key_descriptors_max[] = {
+	0,						   /* version 0 */
+	sizeof(key_desc_v1)/sizeof(struct key_descriptor), /* version 1 */
+};
+
+#define ARRAY_SIZE(a)    (sizeof(a) / sizeof((a)[0]))
+
+static const char* modes[] = {"raw", "ubi"}; /* order isn't arbitrary! */
+
+/* latest version contains all possible keys */
+static const struct key_descriptor *key_desc = key_desc_v1;
+
+#define PFI_IS_UBI(mode) \
+	(((mode) != NULL) && (strcmp("ubi", (mode)) == 0))
+
+#define PFI_IS_RAW(mode) \
+	(((mode) != NULL) && (strcmp("raw", (mode)) == 0))
+
+/**
+ * @return	 <0	On Error.
+ *		>=0	Mode no.
+ */
+static int
+get_mode_no(const char* mode)
+{
+	int i;
+
+	for (i = 0; i < (int)ARRAY_SIZE(modes); i++)
+		if (strcmp(mode, modes[i]) == 0)
+			return i;
+	return -1;
+}
+
+static int
+find_key_by_name (const char *name)
+{
+	int i;
+
+	for (i = 0; i < num_keys; i++) {
+		if (strcmp(name, key_desc[i].name) == 0)
+			return i;
+	}
+	return -1;
+}
+
+static int
+check_valid (pfi_header head)
+{
+	int i;
+	int max_keys;
+	uint32_t version;
+	const char *mode;
+	const struct key_descriptor *desc;
+	uint32_t to_check = PFI_MANDATORY;
+
+	/*
+	 * For the validity check the list of possible keys depends on
+	 * the version of the PFI file used.
+	 */
+	version = head->value[key_version].num;
+	if (version > PFI_HDRVERSION)
+		return PFI_ENOHEADER;
+
+	max_keys = key_descriptors_max[version];
+	desc = key_descriptors[version];
+
+	if (!desc)
+		return PFI_ENOVERSION;
+
+	mode = head->value[key_mode].str;
+	if (PFI_IS_UBI(mode)) {
+		to_check |= PFI_MANDATORY_UBI;
+	}
+	else if (PFI_IS_RAW(mode)) {
+		to_check |= PFI_MANDATORY_RAW;
+	}
+	else { /* neither UBI nor RAW == ERR */
+		return PFI_EINSUFF;
+	}
+
+	for (i = 0; i < max_keys; i++) {
+		if ((desc[i].flags & to_check) && !head->defined[i]) {
+			fprintf(stderr, "libpfi: %s missing\n", desc[i].name);
+			return PFI_EINSUFF;
+		}
+	}
+
+	return 0;
+}
+
+int pfi_header_init (pfi_header *head)
+{
+	int i;
+	pfi_header self = (pfi_header) malloc(sizeof(*self));
+
+	*head = self;
+	if (self == NULL)
+		return PFI_ENOMEM;
+
+	/* initialize maximum number of possible keys */
+	for (i = 0; i < num_keys; i++) {
+		memset(self, 0, sizeof(*self));
+		self->defined[i] = 0;
+	}
+
+	return 0;
+}
+
+int pfi_header_destroy (pfi_header *head)
+{
+	int i;
+	pfi_header self = *head;
+
+	for (i = 0; i < num_keys; i++) {
+		if (self->defined[i] && (key_desc[i].flags & PFI_STRING) &&
+		    self->value[i].str) {
+			free(self->value[i].str);
+		}
+	}
+	free(*head);
+	*head = NULL;
+	return 0;
+}
+
+int pfi_header_setnumber (pfi_header head,
+			   const char *key, uint32_t value)
+{
+	int key_id = find_key_by_name(key);
+
+	if (key_id < 0)
+		return PFI_EUNDEF;
+
+	if (key_desc[key_id].flags & PFI_STRING)
+		return PFI_EBADTYPE;
+
+	head->value[key_id].num = value;
+	head->defined[key_id] = 1;
+	return 0;
+}
+
+int pfi_header_setvalue (pfi_header head,
+			  const char *key, const char *value)
+{
+	int key_id = find_key_by_name(key);
+
+	if (value == NULL)
+		return PFI_EINSUFF;
+
+	if ((key_id < 0) || (key_id >= num_keys))
+		return PFI_EUNDEF;
+
+	if (key_desc[key_id].flags & PFI_STRING) {
+		/*
+		 * The value is a string. Copy to a newly allocated
+		 * buffer. Delete the old value, if already set.
+		 */
+		size_t len = strlen(value) + 1;
+		char *old_str = NULL;
+		char *str;
+
+		old_str = head->value[key_id].str;
+		if (old_str != NULL)
+			free(old_str);
+
+		str = head->value[key_id].str = (char *) malloc(len);
+		if (str == NULL)
+			return PFI_ENOMEM;
+
+		strcpy(str, value);
+	} else {
+		int len;
+		int ret;
+		/* FIXME: here we assume that the value is always
+		   given in hex and starts with '0x'. */
+		ret = sscanf(value, "0x%x%n", &head->value[key_id].num, &len);
+		if (ret < 1 || value[len] != '\0')
+			return PFI_EBADTYPE;
+	}
+	head->defined[key_id] = 1;
+	return 0;
+}
+
+int pfi_header_getnumber (pfi_header head,
+			   const char *key, uint32_t *value)
+{
+	int key_id = find_key_by_name(key);
+
+	if (key_id < 0)
+		return PFI_EUNDEF;
+
+	if (key_desc[key_id].flags & PFI_STRING)
+		return PFI_EBADTYPE;
+
+	if (!head->defined[key_id])
+		return PFI_EUNDEF;
+
+	*value = head->value[key_id].num;
+	return 0;
+}
+
+int pfi_header_getstring (pfi_header head,
+			   const char *key, char *value, size_t size)
+{
+	int key_id = find_key_by_name(key);
+
+	if (key_id < 0)
+		return PFI_EUNDEF;
+
+	if (!(key_desc[key_id].flags & PFI_STRING))
+		return PFI_EBADTYPE;
+
+	if (!head->defined[key_id])
+		return PFI_EUNDEF;
+
+	strncpy(value, head->value[key_id].str, size-1);
+	value[size-1] = '\0';
+	return 0;
+}
+
+int pfi_header_write (FILE *out, pfi_header head)
+{
+	int i;
+	int ret;
+
+	pfi_header_setnumber(head, "version", PFI_HDRVERSION);
+
+	if ((ret = check_valid(head)) != 0)
+		return ret;
+
+	/* OK.	Now write the header. */
+
+	ret = fwrite(PFI_MAGIC, 1, PFI_MAGIC_LEN, out);
+	if (ret < PFI_MAGIC_LEN)
+		return ret;
+
+
+	for (i = 0; i < num_keys; i++) {
+		if (!head->defined[i])
+			continue;
+
+		ret = fprintf(out, "%s=", key_desc[i].name);
+		if (ret < 0)
+			return PFI_EFILE;
+
+		if (key_desc[i].flags & PFI_STRING) {
+			ret = fprintf(out, "%s", head->value[i].str);
+			if (ret < 0)
+				return PFI_EFILE;
+		} else {
+			ret = fprintf(out, "0x%8x", head->value[i].num);
+			if (ret < 0)
+				return PFI_EFILE;
+
+		}
+		ret = fprintf(out, "\n");
+		if (ret < 0)
+			return PFI_EFILE;
+	}
+	ret = fprintf(out, "\n");
+	if (ret < 0)
+		return PFI_EFILE;
+
+	ret = fflush(out);
+	if (ret != 0)
+		return PFI_EFILE;
+
+	return 0;
+}
+
+int pfi_header_read (FILE *in, pfi_header head)
+{
+	char magic[PFI_MAGIC_LEN];
+	char mode[PFI_KEYWORD_LEN];
+	char buf[256];
+
+	if (PFI_MAGIC_LEN != fread(magic, 1, PFI_MAGIC_LEN, in))
+		return PFI_EFILE;
+	if (memcmp(magic, PFI_MAGIC, PFI_MAGIC_LEN) != 0)  {
+		if (memcmp(magic, PFI_DATA, PFI_MAGIC_LEN) == 0) {
+			return PFI_DATA_START;
+		}
+		return PFI_ENOHEADER;
+	}
+
+	while (fgets(buf, sizeof(buf), in) != NULL && buf[0] != '\n') {
+		char *value;
+		char *end;
+		value = strchr(buf, '=');
+		if (value == NULL)
+			return PFI_ENOHEADER;
+
+		*value = '\0';
+		value++;
+		end = strchr(value, '\n');
+		if (end)
+		       *end = '\0';
+
+		if (pfi_header_setvalue(head, buf, value))
+			return PFI_ENOHEADER;
+	}
+
+	if (check_valid(head) != 0)
+		return PFI_ENOHEADER;
+
+	/* set current mode no. in head */
+	pfi_header_getstring(head, "mode", mode, PFI_KEYWORD_LEN);
+	if (head->mode_no > get_mode_no(mode)) {
+		return PFI_EMODE;
+	}
+	head->mode_no = get_mode_no(mode);
+	return 0;
+}
+
+int pfi_header_dump (FILE *out, pfi_header head __attribute__((__unused__)))
+{
+	fprintf(out, "Sorry not implemented yet. Write mail to "
+		"Andreas Arnez and complain!\n");
+	return 0;
+}
+
+int pfi_read (FILE *in, pfi_read_func func, void *priv_data)
+{
+	int rc;
+	pfi_header header;
+
+	rc = pfi_header_init (&header);
+	if (0 != rc)
+		return rc;
+	if (!func)
+		return PFI_EINVAL;
+
+	while ((0 == rc) && !feof(in)) {
+		/*
+		 * Read header and check consistency of the fields.
+		 */
+		rc = pfi_header_read( in, header );
+		if (0 != rc)
+			break;
+		if (func) {
+			rc = func(in, header, priv_data);
+			if (rc != 0)
+				break;
+		}
+	}
+
+	pfi_header_destroy(&header);
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/pfi.h b/ubi-utils/old-utils/src/pfi.h
new file mode 100644
index 0000000..8c5cc07
--- /dev/null
+++ b/ubi-utils/old-utils/src/pfi.h
@@ -0,0 +1,244 @@
+#ifndef __pfi_h
+#define __pfi_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.
+ */
+
+/**
+ * @file pfi.h
+ *
+ * @author Oliver Lohmann <oliloh@de.ibm.com>
+ *         Andreas Arnez <arnez@de.ibm.com>
+ *         Joern Engel <engeljoe@de.ibm.com>
+ *         Frank Haverkamp <haverkam@de.ibm.com>
+ *
+ * @brief libpfi will hold all code to create and process pfi
+ * images. Definitions made in this file are equaly usable for the
+ * development host and the target system.
+ *
+ * @note This header additionally holds the official definitions for
+ * the pfi headers.
+ */
+
+#include <stdio.h>		/* FILE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Definitions. */
+
+#define PFI_HDRVERSION 1	/* current header version */
+
+#define PFI_ENOVERSION 1	/* unknown version */
+#define PFI_ENOHEADER  2	/* not a pfi header */
+#define PFI_EINSUFF    3	/* insufficient information */
+#define PFI_EUNDEF     4	/* key not defined */
+#define PFI_ENOMEM     5	/* out of memory */
+#define PFI_EBADTYPE   6	/* bad data type */
+#define PFI_EFILE      7	/* file I/O error: see errno */
+#define PFI_EFILEINVAL 8	/* file format not valid */
+#define PFI_EINVAL     9	/* invalid parameter */
+#define PFI_ERANGE     10	/* invalid range */
+#define PFI_EMODE      11	/* expecting other mode in this header */
+#define PFI_DATA_START 12	/* data section starts */
+#define PFI_EMAX       13	/* should be always larger as the largest
+				   error code */
+
+#define PFI_LABEL_LEN  64	/* This is the maximum length for a
+				   PFI header label */
+#define PFI_KEYWORD_LEN 32	/* This is the maximum length for an
+				   entry in the mode and type fields */
+
+#define PFI_UBI_MAX_VOLUMES 128
+#define PFI_UBI_VOL_NAME_LEN 127
+
+/**
+ * @brief The pfi header allows to set flags which influence the flashing
+ * behaviour.
+ */
+#define PFI_FLAG_PROTECTED   0x00000001
+
+
+/**
+ * @brief Handle to pfi header. Used in most of the functions associated
+ * with pfi file handling.
+ */
+typedef struct pfi_header *pfi_header;
+
+
+/**
+ * @brief Initialize a pfi header object.
+ *
+ * @param head	 Pointer to handle. This function allocates memory
+ *		 for this data structure.
+ * @return	 0 on success, otherwise:
+ *		 PFI_ENOMEM : no memory available for the handle.
+ */
+int pfi_header_init (pfi_header *head);
+
+
+/**
+ * @brief Destroy a pfi header object.
+ *
+ * @param head	 handle. head is invalid after calling this function.
+ * @return	 0 always.
+ */
+int pfi_header_destroy (pfi_header *head);
+
+
+/**
+ * @brief Add a key/value pair to a pfi header object.
+ *
+ * @param head	 handle.
+ * @param key	 pointer to key string. Must be 0 terminated.
+ * @param value	 pointer to value string. Must be 0 terminated.
+ * @return	 0 on success, otherwise:
+ *		 PFI_EUNDEF   : key was not found.
+ *		 PFI_ENOMEM   : no memory available for the handle.
+ *		 PFI_EBADTYPE : value is not an hex string. This happens
+ *				 when the key stores an integer and the
+ *				 new value is not convertable e.g. not in
+ *				 0xXXXXXXXX format.
+ */
+int pfi_header_setvalue (pfi_header head,
+			  const char *key, const char *value);
+
+
+/**
+ * @brief Add a key/value pair to a pfi header object. Provide the
+ * value as a number.
+ *
+ * @param head	 handle.
+ * @param key	 pointer to key string. Must be 0 terminated.
+ * @param value	 value to set.
+ * @return	 0 on success, otherwise:
+ *		 PFI_EUNDEF   : key was not found.
+ *		 PFI_EBADTYPE : value is not a string. This happens
+ *				 when the key stores a string.
+ */
+int pfi_header_setnumber (pfi_header head,
+			   const char *key, uint32_t value);
+
+
+/**
+ * @brief For a given key, return the numerical value stored in a
+ * pfi header object.
+ *
+ * @param head	 handle.
+ * @param key	 pointer to key string. Must be 0 terminated.
+ * @param value	 pointer to value.
+ * @return	 0 on success, otherwise:
+ *		 PFI_EUNDEF   : key was not found.
+ *		 PFI_EBADTYPE : stored value is not an integer but a string.
+ */
+int pfi_header_getnumber (pfi_header head,
+			   const char *key, uint32_t *value);
+
+
+static inline uint32_t
+pfi_getnumber(pfi_header head, const char *key)
+{
+	uint32_t value;
+	pfi_header_getnumber(head, key, &value);
+	return value;
+}
+
+/**
+ * @brief For a given key, return the string value stored in a pfi
+ * header object.
+ *
+ * @param head	 handle.
+ * @param key	 pointer to key string. Must be 0 terminated.
+ * @param value	 pointer to value string. Memory must be allocated by the user.
+ * @return	 0 on success, otherwise:
+ *		 PFI_EUNDEF   : key was not found.
+ *		 PFI_EBADTYPE : stored value is not a string but an integer.
+ */
+int pfi_header_getstring (pfi_header head,
+			   const char *key, char *value, size_t size);
+
+
+/**
+ * @brief Write a pfi header object into a given file.
+ *
+ * @param out	 output stream.
+ * @param head	 handle.
+ * @return	 0 on success, error values otherwise:
+ *		 PFI_EINSUFF   : not all mandatory fields are filled.
+ *		 PFI_ENOHEADER : wrong header version or magic number.
+ *		 -E*		: see <asm/errno.h>.
+ */
+int pfi_header_write (FILE *out, pfi_header head);
+
+
+/**
+ * @brief Read a pfi header object from a given file.
+ *
+ * @param in	 input stream.
+ * @param head	 handle.
+ * @return	 0 on success, error values otherwise:
+ *		 PFI_ENOVERSION: unknown header version.
+ *		 PFI_EFILE     : cannot read enough data.
+ *		 PFI_ENOHEADER : wrong header version or magic number.
+ *		 -E*		: see <asm/errno.h>.
+ *
+ * If the header verification returned success the user can assume that
+ * all mandatory fields for a particular version are accessible. Checking
+ * the return code when calling the get-function for those keys is not
+ * required in those cases. For optional fields the checking must still be
+ * done.
+ */
+int pfi_header_read (FILE *in, pfi_header head);
+
+
+/**
+ * @brief Display a pfi header in human-readable form.
+ *
+ * @param out	 output stream.
+ * @param head	 handle.
+ * @return	 always 0.
+ *
+ * @note Prints out that it is not implemented and whom you should
+ * contact if you need it urgently!.
+ */
+int pfi_header_dump (FILE *out, pfi_header head);
+
+
+/*
+ * @brief	 Iterates over a stream of pfi files. The iterator function
+ *		 must advance the file pointer in FILE *in to the next pfi
+ *		 header. Function exists on feof(in).
+ *
+ * @param in	 input file descriptor, must be open and valid.
+ * @param func	 iterator function called when pfi header could be
+ *		 read and was validated. The function must return 0 on
+ *		 success.
+ * @return	 See pfi_header_init and pfi_header_read.
+ *		 PFI_EINVAL	  : func is not valid
+ *		 0 ok.
+ */
+typedef int (* pfi_read_func)(FILE *in, pfi_header hdr, void *priv_data);
+
+int pfi_read (FILE *in, pfi_read_func func, void *priv_data);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __pfi_h */
diff --git a/ubi-utils/old-utils/src/pfi2bin.c b/ubi-utils/old-utils/src/pfi2bin.c
new file mode 100644
index 0000000..34ecc92
--- /dev/null
+++ b/ubi-utils/old-utils/src/pfi2bin.c
@@ -0,0 +1,682 @@
+/*
+ * 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
+ *
+ * Convert a PFI file (partial flash image) into a plain binary file.
+ * This tool can be used to prepare the data to be burned into flash
+ * chips in a manufacturing step where the flashes are written before
+ * being soldered onto the hardware. For NAND images another step is
+ * required to add the right OOB data to the binary image.
+ *
+ * 1.3 Removed argp because we want to use uClibc.
+ * 1.4 Minor cleanups
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <ubigen.h>
+#include <mtd/ubi-media.h>
+#include <mtd_swab.h>
+
+#include "config.h"
+#include "list.h"
+#include "error.h"
+#include "reader.h"
+#include "peb.h"
+#include "crc32.h"
+
+#define PROGRAM_VERSION "1.4"
+
+#define MAX_FNAME 255
+#define DEFAULT_ERASE_COUNT  0 /* Hmmm.... Perhaps */
+#define ERR_BUF_SIZE 1024
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+static uint32_t crc32_table[256];
+static char err_buf[ERR_BUF_SIZE];
+
+/*
+ * Data used to buffer raw blocks which have to be
+ * located at a specific point inside the generated RAW file
+ */
+
+typedef enum action_t {
+	ACT_NOTHING   = 0x00000000,
+	ACT_RAW	   = 0x00000001,
+} action_t;
+
+static const char copyright [] __attribute__((unused)) =
+	"(c) Copyright IBM Corp 2006\n";
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+	"pfi2bin - a tool to convert PFI files into binary images.\n";
+
+static const char *optionsstr =
+" Common settings:\n"
+"  -c, --copyright\n"
+"  -v, --verbose              Print more information.\n"
+"\n"
+" Input:\n"
+"  -j, --platform=pdd-file    PDD information which contains the card settings.\n"
+"\n"
+" Output:\n"
+"  -o, --output=filename      Outputfile, default: stdout.\n"
+"\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: pfi2bin [-cv?V] [-j pdd-file] [-o filename] [--copyright]\n"
+"            [--verbose] [--platform=pdd-file] [--output=filename] [--help]\n"
+"            [--usage] [--version] pfifile\n";
+
+struct option long_options[] = {
+	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
+	{ .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "platform", .has_arg = 1, .flag = NULL, .val = 'j' },
+	{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
+	{ .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}
+};
+
+typedef struct io {
+	FILE* fp_pdd;	/* a FilePointer to the PDD data */
+	FILE* fp_pfi;	/* a FilePointer to the PFI input stream */
+	FILE* fp_out;	/* a FilePointer to the output stream */
+} *io_t;
+
+typedef struct myargs {
+	/* common settings */
+	action_t action;
+	int verbose;
+	const char *f_in_pfi;
+	const char *f_in_pdd;
+	const char *f_out;
+
+	/* special stuff needed to get additional arguments */
+	char *arg1;
+	char **options;			/* [STRING...] */
+} myargs;
+
+static int
+parse_opt(int argc, char **argv, myargs *args)
+{
+	while (1) {
+		int key;
+
+		key = getopt_long(argc, argv, "cvj:o:?V", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+			/* common settings */
+			case 'v': /* --verbose=<level> */
+				args->verbose = 1;
+				break;
+
+			case 'c': /* --copyright */
+				fprintf(stderr, "%s\n", copyright);
+				exit(0);
+				break;
+
+			case 'j': /* --platform */
+				args->f_in_pdd = optarg;
+				break;
+
+			case 'o': /* --output */
+				args->f_out = optarg;
+				break;
+
+			case '?': /* help */
+				printf("pfi2bin [OPTION...] pfifile\n");
+				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);
+		}
+	}
+
+	if (optind < argc)
+		args->f_in_pfi = argv[optind++];
+
+	return 0;
+}
+
+
+static size_t
+byte_to_blk(size_t byte, size_t blk_size)
+{
+	return	(byte % blk_size) == 0
+		? byte / blk_size
+		: byte / blk_size + 1;
+}
+
+
+
+
+/**
+ * @precondition  IO: File stream points to first byte of RAW data.
+ * @postcondition IO: File stream points to first byte of next
+ *		      or EOF.
+ */
+static int
+memorize_raw_eb(pfi_raw_t pfi_raw, pdd_data_t pdd, list_t *raw_pebs,
+		io_t io)
+{
+	int rc = 0;
+	uint32_t i;
+
+	size_t read, to_read, eb_num;
+	size_t bytes_left;
+	list_t pebs = *raw_pebs;
+	peb_t	peb  = NULL;
+
+	long old_file_pos = ftell(io->fp_pfi);
+	for (i = 0; i < pfi_raw->starts_size; i++) {
+		bytes_left = pfi_raw->data_size;
+		rc = fseek(io->fp_pfi, old_file_pos, SEEK_SET);
+		if (rc != 0)
+			goto err;
+
+		eb_num = byte_to_blk(pfi_raw->starts[i], pdd->eb_size);
+		while (bytes_left) {
+			to_read = MIN(bytes_left, pdd->eb_size);
+			rc = peb_new(eb_num++, pdd->eb_size, &peb);
+			if (rc != 0)
+				goto err;
+			read = fread(peb->data, 1, to_read, io->fp_pfi);
+			if (read != to_read) {
+				rc = -EIO;
+				goto err;
+			}
+			pebs = append_elem(peb, pebs);
+			bytes_left -= read;
+		}
+
+	}
+	*raw_pebs = pebs;
+	return 0;
+err:
+	pebs = remove_all((free_func_t)&peb_free, pebs);
+	return rc;
+}
+
+static int
+convert_ubi_volume(pfi_ubi_t ubi, pdd_data_t pdd, list_t raw_pebs,
+		struct ubi_vtbl_record *vol_tab,
+		size_t *ebs_written, io_t io)
+{
+	int rc = 0;
+	uint32_t i, j;
+	peb_t raw_peb;
+	peb_t cmp_peb;
+	ubi_info_t u;
+	size_t leb_total = 0;
+	uint8_t vol_type;
+
+	switch (ubi->type) {
+	case pfi_ubi_static:
+		vol_type = UBI_VID_STATIC; break;
+	case pfi_ubi_dynamic:
+		vol_type = UBI_VID_DYNAMIC; break;
+	default:
+		vol_type = UBI_VID_DYNAMIC;
+	}
+
+	rc = peb_new(0, 0, &cmp_peb);
+	if (rc != 0)
+		goto err;
+
+	long old_file_pos = ftell(io->fp_pfi);
+	for (i = 0; i < ubi->ids_size; i++) {
+		rc = fseek(io->fp_pfi, old_file_pos, SEEK_SET);
+		if (rc != 0)
+			goto err;
+		rc = ubigen_create(&u, ubi->ids[i], vol_type,
+				   pdd->eb_size, DEFAULT_ERASE_COUNT,
+				   ubi->alignment, UBI_VERSION,
+				   pdd->vid_hdr_offset, 0, ubi->data_size,
+				   io->fp_pfi, io->fp_out);
+		if (rc != 0)
+			goto err;
+
+		rc = ubigen_get_leb_total(u, &leb_total);
+		if (rc != 0)
+			goto err;
+
+		j = 0;
+		while(j < leb_total) {
+			cmp_peb->num = *ebs_written;
+			raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb,
+					raw_pebs);
+			if (raw_peb) {
+				rc = peb_write(io->fp_out, raw_peb);
+			}
+			else {
+				rc = ubigen_write_leb(u, NO_ERROR);
+				j++;
+			}
+			if (rc != 0)
+				goto err;
+			(*ebs_written)++;
+		}
+		/* memorize volume table entry */
+		rc = ubigen_set_lvol_rec(u, ubi->size,
+				ubi->names[i],
+				(void*) &vol_tab[ubi->ids[i]]);
+		if (rc != 0)
+			goto err;
+		ubigen_destroy(&u);
+	}
+
+	peb_free(&cmp_peb);
+	return 0;
+
+err:
+	peb_free(&cmp_peb);
+	ubigen_destroy(&u);
+	return rc;
+}
+
+
+static FILE*
+my_fmemopen (void *buf, size_t size, const char *opentype)
+{
+    FILE* f;
+    size_t ret;
+
+    assert(strcmp(opentype, "r") == 0);
+
+    f = tmpfile();
+    ret = fwrite(buf, 1, size, f);
+    rewind(f);
+
+    return f;
+}
+
+/**
+ * @brief		Builds a UBI volume table from a volume entry list.
+ * @return 0		On success.
+ *	   else		Error.
+ */
+static int
+write_ubi_volume_table(pdd_data_t pdd, list_t raw_pebs,
+		struct ubi_vtbl_record *vol_tab, size_t vol_tab_size,
+		size_t *ebs_written, io_t io)
+{
+	int rc = 0;
+	ubi_info_t u;
+	peb_t raw_peb;
+	peb_t cmp_peb;
+	size_t leb_size, leb_total, j = 0;
+	uint8_t *ptr = NULL;
+	FILE* fp_leb = NULL;
+	int vt_slots;
+	size_t vol_tab_size_limit;
+
+	rc = peb_new(0, 0, &cmp_peb);
+	if (rc != 0)
+		goto err;
+
+	/* @FIXME: Artem creates one volume with 2 LEBs.
+	 * IMO 2 volumes would be more convenient. In order
+	 * to get 2 reserved LEBs from ubigen, I have to
+	 * introduce this stupid mechanism. Until no final
+	 * decision of the VTAB structure is made... Good enough.
+	 */
+	rc = ubigen_create(&u, UBI_LAYOUT_VOLUME_ID, UBI_VID_DYNAMIC,
+			   pdd->eb_size, DEFAULT_ERASE_COUNT,
+			   1, UBI_VERSION,
+			   pdd->vid_hdr_offset, UBI_COMPAT_REJECT,
+			   vol_tab_size, stdin, io->fp_out);
+			   /* @FIXME stdin for fp_in is a hack */
+	if (rc != 0)
+		goto err;
+	rc = ubigen_get_leb_size(u, &leb_size);
+	if (rc != 0)
+		goto err;
+	ubigen_destroy(&u);
+
+	/*
+	 * The number of supported volumes is restricted by the eraseblock size
+	 * and by the UBI_MAX_VOLUMES constant.
+	 */
+	vt_slots = leb_size / UBI_VTBL_RECORD_SIZE;
+	if (vt_slots > UBI_MAX_VOLUMES)
+		vt_slots = UBI_MAX_VOLUMES;
+	vol_tab_size_limit = vt_slots * UBI_VTBL_RECORD_SIZE;
+
+	ptr = (uint8_t*) malloc(leb_size * sizeof(uint8_t));
+	if (ptr == NULL)
+		goto err;
+
+	memset(ptr, 0xff, leb_size);
+	memcpy(ptr, vol_tab, vol_tab_size_limit);
+	fp_leb = my_fmemopen(ptr, leb_size, "r");
+
+	rc = ubigen_create(&u, UBI_LAYOUT_VOLUME_ID, UBI_VID_DYNAMIC,
+			   pdd->eb_size, DEFAULT_ERASE_COUNT,
+			   1, UBI_VERSION, pdd->vid_hdr_offset,
+			   UBI_COMPAT_REJECT, leb_size * UBI_LAYOUT_VOLUME_EBS,
+			   fp_leb, io->fp_out);
+	if (rc != 0)
+		goto err;
+	rc = ubigen_get_leb_total(u, &leb_total);
+	if (rc != 0)
+		goto err;
+
+	long old_file_pos = ftell(fp_leb);
+	while(j < leb_total) {
+		rc = fseek(fp_leb, old_file_pos, SEEK_SET);
+		if (rc != 0)
+			goto err;
+
+		cmp_peb->num = *ebs_written;
+		raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb,
+				raw_pebs);
+		if (raw_peb) {
+			rc = peb_write(io->fp_out, raw_peb);
+		}
+		else {
+			rc = ubigen_write_leb(u, NO_ERROR);
+			j++;
+		}
+
+		if (rc != 0)
+			goto err;
+		(*ebs_written)++;
+	}
+
+err:
+	free(ptr);
+	peb_free(&cmp_peb);
+	ubigen_destroy(&u);
+	fclose(fp_leb);
+	return rc;
+}
+
+static int
+write_remaining_raw_ebs(pdd_data_t pdd, list_t raw_blocks, size_t *ebs_written,
+			FILE* fp_out)
+{
+	int rc = 0;
+	uint32_t j, delta;
+	list_t ptr;
+	peb_t empty_eb, peb;
+
+	/* create an empty 0xff EB (for padding) */
+	rc = peb_new(0, pdd->eb_size, &empty_eb);
+
+	foreach(peb, ptr, raw_blocks) {
+		if (peb->num < *ebs_written) {
+			continue; /* omit blocks which
+				     are already passed */
+		}
+
+		if (peb->num < *ebs_written) {
+			err_msg("eb_num: %d\n", peb->num);
+			err_msg("Bug: This should never happen. %d %s",
+				__LINE__, __FILE__);
+			goto err;
+		}
+
+		delta = peb->num - *ebs_written;
+		if (((delta + *ebs_written) * pdd->eb_size) > pdd->flash_size) {
+			err_msg("RAW block outside of flash_size.");
+			goto err;
+		}
+		for (j = 0; j < delta; j++) {
+			rc = peb_write(fp_out, empty_eb);
+			if (rc != 0)
+				goto err;
+			(*ebs_written)++;
+		}
+		rc = peb_write(fp_out, peb);
+		if (rc != 0)
+			goto err;
+		(*ebs_written)++;
+	}
+
+err:
+	peb_free(&empty_eb);
+	return rc;
+}
+
+static int
+init_vol_tab(struct ubi_vtbl_record **vol_tab, size_t *vol_tab_size)
+{
+	uint32_t crc;
+	size_t i;
+	struct ubi_vtbl_record* res = NULL;
+
+	*vol_tab_size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
+
+	res = (struct ubi_vtbl_record*) calloc(1, *vol_tab_size);
+	if (vol_tab == NULL) {
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < UBI_MAX_VOLUMES; i++) {
+		crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
+			&(res[i]), UBI_VTBL_RECORD_SIZE_CRC);
+		res[i].crc = cpu_to_be32(crc);
+	}
+
+	*vol_tab = res;
+	return 0;
+}
+
+static int
+create_raw(io_t io)
+{
+	int rc = 0;
+	size_t ebs_written = 0; /* eraseblocks written already... */
+	size_t vol_tab_size;
+	list_t ptr;
+
+	list_t pfi_raws = mk_empty(); /* list of raw sections from a pfi */
+	list_t pfi_ubis = mk_empty(); /* list of ubi sections from a pfi */
+	list_t raw_pebs	 = mk_empty(); /* list of raw eraseblocks */
+
+	struct ubi_vtbl_record *vol_tab = NULL;
+	pdd_data_t pdd = NULL;
+
+	rc = init_vol_tab (&vol_tab, &vol_tab_size);
+	if (rc != 0) {
+		err_msg("Cannot initialize volume table.");
+		goto err;
+	}
+
+	rc = read_pdd_data(io->fp_pdd, &pdd,
+			err_buf, ERR_BUF_SIZE);
+	if (rc != 0) {
+		err_msg("Cannot read necessary pdd_data: %s rc: %d",
+				err_buf, rc);
+		goto err;
+	}
+
+	rc = read_pfi_headers(&pfi_raws, &pfi_ubis, io->fp_pfi,
+			err_buf, ERR_BUF_SIZE);
+	if (rc != 0) {
+		err_msg("Cannot read pfi header: %s rc: %d",
+				err_buf, rc);
+		goto err;
+	}
+
+	pfi_raw_t pfi_raw;
+	foreach(pfi_raw, ptr, pfi_raws) {
+		rc = memorize_raw_eb(pfi_raw, pdd, &raw_pebs,
+			io);
+		if (rc != 0) {
+			err_msg("Cannot create raw_block in mem. rc: %d\n",
+				rc);
+			goto err;
+		}
+	}
+
+	pfi_ubi_t pfi_ubi;
+	foreach(pfi_ubi, ptr, pfi_ubis) {
+		rc = convert_ubi_volume(pfi_ubi, pdd, raw_pebs,
+					vol_tab, &ebs_written, io);
+		if (rc != 0) {
+			err_msg("Cannot convert UBI volume. rc: %d\n", rc);
+			goto err;
+		}
+	}
+
+	rc = write_ubi_volume_table(pdd, raw_pebs, vol_tab, vol_tab_size,
+			&ebs_written, io);
+	if (rc != 0) {
+		err_msg("Cannot write UBI volume table. rc: %d\n", rc);
+		goto err;
+	}
+
+	rc  = write_remaining_raw_ebs(pdd, raw_pebs, &ebs_written, io->fp_out);
+	if (rc != 0)
+		goto err;
+
+	if (io->fp_out != stdout)
+		info_msg("Physical eraseblocks written: %8d\n", ebs_written);
+err:
+	free(vol_tab);
+	pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws);
+	pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis);
+	raw_pebs = remove_all((free_func_t)&peb_free, raw_pebs);
+	free_pdd_data(&pdd);
+	return rc;
+}
+
+
+/* ------------------------------------------------------------------------- */
+static void
+open_io_handle(myargs *args, io_t io)
+{
+	/* set PDD input */
+	io->fp_pdd = fopen(args->f_in_pdd, "r");
+	if (io->fp_pdd == NULL) {
+		err_sys("Cannot open: %s", args->f_in_pdd);
+	}
+
+	/* set PFI input */
+	io->fp_pfi = fopen(args->f_in_pfi, "r");
+	if (io->fp_pfi == NULL) {
+		err_sys("Cannot open PFI input file: %s", args->f_in_pfi);
+	}
+
+	/* set output prefix */
+	if (strcmp(args->f_out,"") == 0)
+		io->fp_out = stdout;
+	else {
+		io->fp_out = fopen(args->f_out, "wb");
+		if (io->fp_out == NULL) {
+			err_sys("Cannot open output file: %s", args->f_out);
+		}
+	}
+}
+
+static void
+close_io_handle(io_t io)
+{
+	if (fclose(io->fp_pdd) != 0) {
+		err_sys("Cannot close PDD file.");
+	}
+	if (fclose(io->fp_pfi) != 0) {
+		err_sys("Cannot close PFI file.");
+	}
+	if (io->fp_out != stdout) {
+		if (fclose(io->fp_out) != 0) {
+			err_sys("Cannot close output file.");
+		}
+	}
+
+	io->fp_pdd = NULL;
+	io->fp_pfi = NULL;
+	io->fp_out = NULL;
+}
+
+int
+main(int argc, char *argv[])
+{
+	int rc = 0;
+
+	ubigen_init();
+	init_crc32_table(crc32_table);
+
+	struct io io = {NULL, NULL, NULL};
+	myargs args = {
+		.action = ACT_RAW,
+		.verbose = 0,
+
+		.f_in_pfi = "",
+		.f_in_pdd = "",
+		.f_out = "",
+
+		/* arguments */
+		.arg1 = NULL,
+		.options = NULL,
+	};
+
+	/* parse arguments */
+	parse_opt(argc, argv, &args);
+
+	if (strcmp(args.f_in_pfi, "") == 0) {
+		err_quit("No PFI input file specified!");
+	}
+
+	if (strcmp(args.f_in_pdd, "") == 0) {
+		err_quit("No PDD input file specified!");
+	}
+
+	open_io_handle(&args, &io);
+
+	info_msg("[ Creating RAW...");
+	rc = create_raw(&io);
+	if (rc != 0) {
+		err_msg("Creating RAW failed.");
+		goto err;
+	}
+
+err:
+	close_io_handle(&io);
+	if (rc != 0) {
+		remove(args.f_out);
+	}
+
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/pfiflash.c b/ubi-utils/old-utils/src/pfiflash.c
new file mode 100644
index 0000000..754fe33
--- /dev/null
+++ b/ubi-utils/old-utils/src/pfiflash.c
@@ -0,0 +1,264 @@
+/*
+ * 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
+ *         Frank Haverkamp
+ *
+ * Process a PFI (partial flash image) and write the data to the
+ * specified UBI volumes. This tool is intended to be used for system
+ * update using PFI files.
+ *
+ * 1.1 fixed output to stderr and stdout in logfile mode.
+ * 1.2 updated.
+ * 1.3 removed argp parsing to be able to use uClib.
+ * 1.4 Minor cleanups.
+ * 1.5 Forgot to delete raw block before updating it.
+ * 1.6 Migrated to new libubi.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <pfiflash.h>
+#undef DEBUG
+#include "error.h"
+#include "config.h"
+
+#define PROGRAM_VERSION  "1.6"
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+	"pfiflash - a tool for updating a controller with PFI files.\n";
+
+static const char *optionsstr =
+" Standard options:\n"
+"  -c, --copyright            Print copyright information.\n"
+"  -l, --logfile=<file>       Write a logfile to <file>.\n"
+"  -v, --verbose              Be verbose during program execution.\n"
+"\n"
+" Process options:\n"
+"  -C, --complete             Execute a complete system update. Updates both\n"
+"                             sides.\n"
+"  -p, --pdd-update=<type>    Specify the pdd-update algorithm. <type> is either\n"
+"                             'keep', 'merge' or 'overwrite'.\n"
+"  -r, --raw-flash=<dev>      Flash the raw data. Use the specified mtd device.\n"
+"  -s, --side=<seqnum>        Select the side which shall be updated.\n"
+"  -x, --compare              Only compare on-flash and pfi data, print info if\n"
+"                             an update is neccessary and return appropriate\n"
+"                             error code.\n"
+"\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: pfiflash [-cvC?V] [-l <file>] [-p <type>] [-r <dev>] [-s <seqnum>]\n"
+"            [--copyright] [--logfile=<file>] [--verbose] [--complete]\n"
+"            [--pdd-update=<type>] [--raw-flash=<dev>] [--side=<seqnum>]\n"
+"            [--compare] [--help] [--usage] [--version] [pfifile]\n";
+
+static const char copyright [] __attribute__((unused)) =
+	"Copyright IBM Corp 2006";
+
+struct option long_options[] = {
+	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
+	{ .name = "logfile", .has_arg = 1, .flag = NULL, .val = 'l' },
+	{ .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "complete", .has_arg = 0, .flag = NULL, .val = 'C' },
+	{ .name = "pdd-update", .has_arg = 1, .flag = NULL, .val = 'p' },
+	{ .name = "raw-flash", .has_arg = 1, .flag = NULL, .val = 'r' },
+	{ .name = "side", .has_arg = 1, .flag = NULL, .val = 's' },
+	{ .name = "compare", .has_arg = 0, .flag = NULL, .val = 'x' },
+	{ .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}
+};
+
+typedef struct myargs {
+	int verbose;
+	const char *logfile;
+	const char *raw_dev;
+
+	pdd_handling_t pdd_handling;
+	int seqnum;
+	int compare;
+	int complete;
+
+	FILE* fp_in;
+
+	/* special stuff needed to get additional arguments */
+	char *arg1;
+	char **options;		/* [STRING...] */
+} myargs;
+
+static pdd_handling_t
+get_pdd_handling(const char* str)
+{
+	if (strcmp(str, "keep") == 0) {
+		return PDD_KEEP;
+	}
+	if (strcmp(str, "merge") == 0) {
+		return PDD_MERGE;
+	}
+	if (strcmp(str, "overwrite") == 0) {
+		return PDD_OVERWRITE;
+	}
+
+	return -1;
+}
+
+static int
+get_update_seqnum(const char* str)
+{
+	uint32_t i = strtoul(str, NULL, 0);
+
+	if ((i != 0) && (i != 1)) {
+		return -1;
+	}
+
+	return i;
+}
+
+
+static int
+parse_opt(int argc, char **argv, myargs *args)
+{
+	while (1) {
+		int key;
+
+		key = getopt_long(argc, argv, "cl:vCp:r:s:x?V",
+				  long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+			/* standard options */
+			case 'c':
+				err_msg("%s\n", copyright);
+				exit(0);
+				break;
+			case 'v':
+				args->verbose = 1;
+				break;
+			case 'l':
+				args->logfile = optarg;
+				break;
+				/* process options */
+			case 'C':
+				args->complete = 1;
+				break;
+			case 'p':
+				args->pdd_handling = get_pdd_handling(optarg);
+				if ((int)args->pdd_handling < 0) {
+					err_quit("Unknown PDD handling: %s.\n"
+						 "Please use either "
+						 "'keep', 'merge' or"
+						 "'overwrite'.\n'");
+				}
+				break;
+			case 's':
+				args->seqnum = get_update_seqnum(optarg);
+				if (args->seqnum < 0) {
+					err_quit("Unsupported side: %s.\n"
+						 "Supported sides are '0' "
+						 "and '1'\n", optarg);
+				}
+				break;
+			case 'x':
+				args->compare = 1;
+				break;
+			case 'r':
+				args->raw_dev = optarg;
+				break;
+			case '?': /* help */
+				err_msg("Usage: pfiflash [OPTION...] [pfifile]");
+				err_msg("%s", doc);
+				err_msg("%s", optionsstr);
+				err_msg("\nReport bugs to %s\n",
+					PACKAGE_BUGREPORT);
+				exit(0);
+				break;
+			case 'V':
+				err_msg("%s", PROGRAM_VERSION);
+				exit(0);
+				break;
+			default:
+				err_msg("%s", usage);
+				exit(-1);
+
+		}
+	}
+
+	if (optind < argc) {
+		args->fp_in = fopen(argv[optind++], "r");
+		if ((args->fp_in) == NULL) {
+			err_sys("Cannot open PFI file %s for input",
+				argv[optind]);
+		}
+	}
+
+	return 0;
+}
+
+int main (int argc, char** argv)
+{
+	int rc = 0;
+	char err_buf[PFIFLASH_MAX_ERR_BUF_SIZE];
+	memset(err_buf, '\0', PFIFLASH_MAX_ERR_BUF_SIZE);
+
+	myargs args = {
+		.verbose    = 0,
+		.seqnum	    = -1,
+		.compare    = 0,
+		.complete   = 0,
+		.logfile    = NULL, /* "/tmp/pfiflash.log", */
+		.pdd_handling = PDD_KEEP,
+		.fp_in	    = stdin,
+		.raw_dev    = NULL,
+	};
+
+	parse_opt(argc, argv, &args);
+	error_initlog(args.logfile);
+
+	if (!args.fp_in) {
+		rc = -1;
+		snprintf(err_buf, PFIFLASH_MAX_ERR_BUF_SIZE,
+			 "No PFI input file specified!\n");
+		goto err;
+	}
+
+	rc = pfiflash_with_options(args.fp_in, args.complete, args.seqnum,
+			args.compare, args.pdd_handling, args.raw_dev, err_buf,
+			PFIFLASH_MAX_ERR_BUF_SIZE);
+	if (rc < 0) {
+		goto err_fp;
+	}
+
+ err_fp:
+	if (args.fp_in != stdin)
+		fclose(args.fp_in);
+ err:
+	if (rc != 0)
+		err_msg("pfiflash: %s\nrc: %d\n", err_buf, rc);
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/pfiflash.h b/ubi-utils/old-utils/src/pfiflash.h
new file mode 100644
index 0000000..039705d
--- /dev/null
+++ b/ubi-utils/old-utils/src/pfiflash.h
@@ -0,0 +1,76 @@
+#ifndef __PFIFLASH_H__
+#define __PFIFLASH_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.
+ */
+
+/**
+ *
+ * @file pfi.h
+ *
+ * @author Oliver Lohmann <oliloh@de.ibm.com>
+ *
+ * @brief The pfiflash library offers an interface for using the
+ * pfiflash * utility.
+ */
+
+#include <stdio.h>		/* FILE */
+
+#define PFIFLASH_MAX_ERR_BUF_SIZE 1024
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum pdd_handling_t
+{
+	PDD_KEEP = 0,
+	PDD_MERGE,
+	PDD_OVERWRITE,
+	PDD_HANDLING_NUM, /* always the last item */
+} pdd_handling_t; /**< Possible PDD handle algorithms. */
+
+/**
+ * @brief Flashes a PFI file to UBI Device 0.
+ * @param complete	[0|1] Do a complete system update.
+ * @param seqnum	Index in a redundant group.
+ * @param compare	[0|1] Compare contents.
+ * @param pdd_handling	The PDD handling algorithm.
+ * @param rawdev	Device to use for raw flashing
+ * @param err_buf	An error buffer.
+ * @param err_buf_size	Size of the error buffer.
+ */
+int pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare,
+		pdd_handling_t pdd_handling, const char* rawdev,
+		char *err_buf, size_t err_buf_size);
+
+/**
+ * @brief Flashes a PFI file to UBI Device 0.
+ * @param complete	[0|1] Do a complete system update.
+ * @param seqnum	Index in a redundant group.
+ * @param pdd_handling	The PDD handling algorithm.
+ * @param err_buf	An error buffer.
+ * @param err_buf_size	Size of the error buffer.
+ */
+int pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling,
+		char *err_buf, size_t err_buf_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PFIFLASH_H__ */
diff --git a/ubi-utils/old-utils/src/pfiflash_error.h b/ubi-utils/old-utils/src/pfiflash_error.h
new file mode 100644
index 0000000..0f27f4a
--- /dev/null
+++ b/ubi-utils/old-utils/src/pfiflash_error.h
@@ -0,0 +1,75 @@
+#ifndef __PFIFLASH_ERROR_H__
+#define __PFIFLASH_ERROR_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: Drake Dowsett <dowsett@de.ibm.com>
+ * Contact: Andreas Arnez <arnez@de.ibm.com>
+ */
+
+enum pfiflash_err {
+	PFIFLASH_ERR_EOF = 1,
+	PFIFLASH_ERR_FIO,
+	PFIFLASH_ERR_UBI_OPEN,
+	PFIFLASH_ERR_UBI_CLOSE,
+	PFIFLASH_ERR_UBI_MKVOL,
+	PFIFLASH_ERR_UBI_RMVOL,
+	PFIFLASH_ERR_UBI_VOL_UPDATE,
+	PFIFLASH_ERR_UBI_VOL_FOPEN,
+	PFIFLASH_ERR_UBI_UNKNOWN,
+	PFIFLASH_ERR_UBI_VID_OOB,
+	PFIFLASH_ERR_BOOTENV_CREATE,
+	PFIFLASH_ERR_BOOTENV_READ,
+	PFIFLASH_ERR_BOOTENV_SIZE,
+	PFIFLASH_ERR_BOOTENV_WRITE,
+	PFIFLASH_ERR_PDD_UNKNOWN,
+	PFIFLASH_ERR_MTD_OPEN,
+	PFIFLASH_ERR_MTD_CLOSE,
+	PFIFLASH_ERR_CRC_CHECK,
+	PFIFLASH_ERR_MTD_ERASE,
+	PFIFLASH_ERR_COMPARE,
+	PFIFLASH_CMP_DIFF
+};
+
+const char *const PFIFLASH_ERRSTR[] = {
+	"",
+	"unexpected EOF",
+	"file I/O error",
+	"couldn't open UBI",
+	"couldn't close UBI",
+	"couldn't make UBI volume %d",
+	"couldn't remove UBI volume %d",
+	"couldn't update UBI volume %d",
+	"couldn't open UBI volume %d",
+	"unknown UBI operation",
+	"PFI data contains out of bounds UBI id %d",
+	"couldn't create bootenv%s",
+	"couldn't read bootenv",
+	"couldn't resize bootenv",
+	"couldn't write bootenv on ubi%d_%d",
+	"unknown PDD handling algorithm",
+	"couldn't open MTD device %s",
+	"couldn't close MTD device %s",
+	"CRC check failed: given=0x%08x, calculated=0x%08x",
+	"couldn't erase raw mtd region",
+	"couldn't compare volumes",
+	"on-flash data differ from pfi data, update is neccessary"
+};
+
+#endif /* __PFIFLASH_ERROR_H__ */
diff --git a/ubi-utils/old-utils/src/reader.c b/ubi-utils/old-utils/src/reader.c
new file mode 100644
index 0000000..0ea8c6d
--- /dev/null
+++ b/ubi-utils/old-utils/src/reader.c
@@ -0,0 +1,482 @@
+/*
+ * 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
+ *
+ * Read in PFI (partial flash image) data and store it into internal
+ * data structures for further processing. Take also care about
+ * special handling if the data contains PDD (platform description
+ * data/boot-parameters).
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "bootenv.h"
+#include "reader.h"
+
+#define __unused __attribute__((unused))
+
+/* @FIXME hard coded offsets right now - get them from Artem? */
+#define NAND2048_DEFAULT_VID_HDR_OFF 1984
+#define NAND512_DEFAULT_VID_HDR_OFF  448
+#define NOR_DEFAULT_VID_HDR_OFF      64
+
+#define EBUF_PFI(fmt...)						\
+	do { int i = snprintf(err_buf, err_buf_size, "%s\n", label);	\
+	     snprintf(err_buf + i, err_buf_size - i, fmt);		\
+	} while (0)
+
+#define EBUF(fmt...) \
+	do { snprintf(err_buf, err_buf_size, fmt); } while (0)
+
+
+int
+read_pdd_data(FILE* fp_pdd, pdd_data_t* pdd_data,
+	      char* err_buf, size_t err_buf_size)
+{
+	int rc = 0;
+	bootenv_t pdd = NULL;
+	pdd_data_t res = NULL;
+	const char* value;
+
+	res = (pdd_data_t) malloc(sizeof(struct pdd_data));
+	if (!res) {
+		rc = -ENOMEM;
+		goto err;
+	}
+	rc = bootenv_create(&pdd);
+	if (rc != 0) {
+		goto err;
+	}
+	rc = bootenv_read_txt(fp_pdd, pdd);
+	if (rc != 0) {
+		goto err;
+	}
+	rc = bootenv_get(pdd, "flash_type", &value);
+	if (rc != 0) {
+		goto err;
+	}
+
+	if (strcmp(value, "NAND") == 0) {
+
+		rc = bootenv_get_num(pdd, "flash_page_size",
+			     &(res->flash_page_size));
+		if (rc != 0) {
+			EBUF("Cannot read 'flash_page_size' from pdd.");
+			goto err;
+		}
+		res->flash_type = NAND_FLASH;
+
+		switch (res->flash_page_size) {
+		case 512:
+			res->vid_hdr_offset = NAND512_DEFAULT_VID_HDR_OFF;
+			break;
+		case 2048:
+			res->vid_hdr_offset = NAND2048_DEFAULT_VID_HDR_OFF;
+			break;
+		default:
+			EBUF("Unsupported  'flash_page_size' %d.",
+			     res->flash_page_size);
+			goto err;
+		}
+	}
+	else if (strcmp(value, "NOR") == 0){
+		res->flash_type = NOR_FLASH;
+		res->vid_hdr_offset = NOR_DEFAULT_VID_HDR_OFF;
+	}
+	else {
+		snprintf(err_buf, err_buf_size,
+			 "Unkown flash type: %s", value);
+		goto err;
+	}
+
+	rc = bootenv_get_num(pdd, "flash_eraseblock_size",
+			     &(res->eb_size));
+	if (rc != 0) {
+		EBUF("Cannot read 'flash_eraseblock_size' from pdd.");
+		goto err;
+	}
+
+	rc = bootenv_get_num(pdd, "flash_size",
+			     &(res->flash_size));
+	if (rc != 0) {
+		EBUF("Cannot read 'flash_size' from pdd.");
+		goto err;
+	}
+
+	goto out;
+ err:
+	if (res) {
+		free(res);
+		res = NULL;
+	}
+ out:
+	bootenv_destroy(&pdd);
+	*pdd_data = res;
+	return rc;
+}
+
+int
+read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_raw_t* pfi_raw,
+	     const char* label, char* err_buf, size_t err_buf_size)
+{
+	int rc = 0;
+	char tmp_str[PFI_KEYWORD_LEN];
+	bootenv_list_t raw_start_list = NULL;
+	pfi_raw_t res;
+	size_t size;
+
+	res = (pfi_raw_t) malloc(sizeof(struct pfi_raw));
+	if (!res)
+		return -ENOMEM;
+
+	rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size));
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'size' from PFI.");
+		goto err;
+	}
+
+	rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc));
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'crc' from PFI.");
+		goto err;
+	}
+
+	rc = pfi_header_getstring(pfi_hd, "raw_starts",
+				  tmp_str, PFI_KEYWORD_LEN);
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'raw_starts' from PFI.");
+		goto err;
+	}
+
+	rc = bootenv_list_create(&raw_start_list);
+	if (rc != 0) {
+		goto err;
+	}
+
+	rc = bootenv_list_import(raw_start_list, tmp_str);
+	if (rc != 0) {
+		EBUF_PFI("Cannot translate PFI value: %s", tmp_str);
+		goto err;
+	}
+
+	rc = bootenv_list_to_num_vector(raw_start_list,
+					&size, &(res->starts));
+	res->starts_size = size;
+
+	if (rc != 0) {
+		EBUF_PFI("Cannot create numeric value array: %s", tmp_str);
+		goto err;
+	}
+
+	goto out;
+
+ err:
+	if (res) {
+		free(res);
+		res = NULL;
+	}
+ out:
+	bootenv_list_destroy(&raw_start_list);
+	*pfi_raw = res;
+	return rc;
+}
+
+int
+read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi,
+	     const char *label, char* err_buf, size_t err_buf_size)
+{
+	int rc = 0;
+	const char** tmp_names = NULL;
+	char tmp_str[PFI_KEYWORD_LEN];
+	bootenv_list_t ubi_id_list = NULL;
+	bootenv_list_t ubi_name_list = NULL;
+	pfi_ubi_t res;
+	uint32_t i;
+	size_t size;
+
+	res = (pfi_ubi_t) calloc(1, sizeof(struct pfi_ubi));
+	if (!res)
+		return -ENOMEM;
+
+	rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size));
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'size' from PFI.");
+		goto err;
+	}
+
+	rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc));
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'crc' from PFI.");
+		goto err;
+	}
+
+	rc = pfi_header_getstring(pfi_hd, "ubi_ids", tmp_str, PFI_KEYWORD_LEN);
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'ubi_ids' from PFI.");
+		goto err;
+	}
+
+	rc = bootenv_list_create(&ubi_id_list);
+	if (rc != 0) {
+		goto err;
+	}
+	rc = bootenv_list_create(&ubi_name_list);
+	if (rc != 0) {
+		goto err;
+	}
+
+	rc = bootenv_list_import(ubi_id_list, tmp_str);
+	if (rc != 0) {
+		EBUF_PFI("Cannot translate PFI value: %s", tmp_str);
+		goto err;
+	}
+
+	rc = bootenv_list_to_num_vector(ubi_id_list, &size,
+					&(res->ids));
+	res->ids_size = size;
+	if (rc != 0) {
+		EBUF_PFI("Cannot create numeric value array: %s", tmp_str);
+		goto err;
+	}
+
+	if (res->ids_size == 0) {
+		rc = -1;
+		EBUF_PFI("Sanity check failed: No ubi_ids specified.");
+		goto err;
+	}
+
+	rc = pfi_header_getstring(pfi_hd, "ubi_type",
+				  tmp_str, PFI_KEYWORD_LEN);
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'ubi_type' from PFI.");
+		goto err;
+	}
+	if (strcmp(tmp_str, "static") == 0)
+		res->type = pfi_ubi_static;
+	else if (strcmp(tmp_str, "dynamic") == 0)
+		res->type = pfi_ubi_dynamic;
+	else {
+		EBUF_PFI("Unknown ubi_type in PFI.");
+		goto err;
+	}
+
+	rc = pfi_header_getnumber(pfi_hd, "ubi_alignment", &(res->alignment));
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'ubi_alignment' from PFI.");
+		goto err;
+	}
+
+	rc = pfi_header_getnumber(pfi_hd, "ubi_size", &(res->size));
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'ubi_size' from PFI.");
+		goto err;
+	}
+
+	rc = pfi_header_getstring(pfi_hd, "ubi_names",
+				  tmp_str, PFI_KEYWORD_LEN);
+	if (rc != 0) {
+		EBUF_PFI("Cannot read 'ubi_names' from PFI.");
+		goto err;
+	}
+
+	rc = bootenv_list_import(ubi_name_list, tmp_str);
+	if (rc != 0) {
+		EBUF_PFI("Cannot translate PFI value: %s", tmp_str);
+		goto err;
+	}
+	rc = bootenv_list_to_vector(ubi_name_list, &size,
+				    &(tmp_names));
+	res->names_size = size;
+	if (rc != 0) {
+		EBUF_PFI("Cannot create string array: %s", tmp_str);
+		goto err;
+	}
+
+	if (res->names_size != res->ids_size) {
+		EBUF_PFI("Sanity check failed: ubi_ids list does not match "
+			 "sizeof ubi_names list.");
+		rc = -1;
+	}
+
+	/* copy tmp_names to own structure */
+	res->names = (char**) calloc(1, res->names_size * sizeof (char*));
+	if (res->names == NULL)
+		goto err;
+
+	for (i = 0; i < res->names_size; i++) {
+		res->names[i] = calloc(PFI_UBI_VOL_NAME_LEN + 1, sizeof(char));
+		if (res->names[i] == NULL)
+			goto err;
+		strncpy(res->names[i], tmp_names[i], PFI_UBI_VOL_NAME_LEN + 1);
+	}
+
+	goto out;
+
+ err:
+	if (res) {
+		if (res->names) {
+			for (i = 0; i < res->names_size; i++) {
+				if (res->names[i]) {
+					free(res->names[i]);
+				}
+			}
+			free(res->names);
+		}
+		if (res->ids) {
+			free(res->ids);
+		}
+		free(res);
+		res = NULL;
+	}
+
+ out:
+	bootenv_list_destroy(&ubi_id_list);
+	bootenv_list_destroy(&ubi_name_list);
+	if (tmp_names != NULL)
+		free(tmp_names);
+	*pfi_ubi = res;
+	return rc;
+}
+
+
+int
+free_pdd_data(pdd_data_t* pdd_data)
+{
+	if (*pdd_data) {
+		free(*pdd_data);
+	}
+	*pdd_data = NULL;
+
+	return 0;
+}
+
+int
+free_pfi_raw(pfi_raw_t* pfi_raw)
+{
+	pfi_raw_t tmp = *pfi_raw;
+	if (tmp) {
+		if (tmp->starts)
+			free(tmp->starts);
+		free(tmp);
+	}
+	*pfi_raw = NULL;
+
+	return 0;
+}
+
+int
+free_pfi_ubi(pfi_ubi_t* pfi_ubi)
+{
+	size_t i;
+	pfi_ubi_t tmp = *pfi_ubi;
+	if (tmp) {
+		if (tmp->ids)
+			free(tmp->ids);
+		if (tmp->names) {
+			for (i = 0; i < tmp->names_size; i++) {
+				if (tmp->names[i]) {
+					free(tmp->names[i]);
+				}
+			}
+			free(tmp->names);
+		}
+		free(tmp);
+	}
+	*pfi_ubi = NULL;
+
+	return 0;
+}
+
+
+int
+read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi,
+		 char* err_buf, size_t err_buf_size)
+{
+	int rc = 0;
+	char mode[PFI_KEYWORD_LEN];
+	char label[PFI_LABEL_LEN];
+
+	*pfi_raws = mk_empty(); pfi_raw_t raw = NULL;
+	*pfi_ubis = mk_empty(); pfi_ubi_t ubi = NULL;
+	pfi_header pfi_header = NULL;
+
+	/* read all headers from PFI and store them in lists */
+	rc = pfi_header_init(&pfi_header);
+	if (rc != 0) {
+		EBUF("Cannot initialize pfi header.");
+		goto err;
+	}
+	while ((rc == 0) && !feof(fp_pfi)) {
+		rc = pfi_header_read(fp_pfi, pfi_header);
+		if (rc != 0) {
+			if (rc == PFI_DATA_START) {
+				rc = 0;
+				break; /* data section starts,
+					  all headers read */
+			}
+			else {
+				goto err;
+			}
+		}
+		rc = pfi_header_getstring(pfi_header, "label", label,
+					  PFI_LABEL_LEN);
+		if (rc != 0) {
+			EBUF("Cannot read 'label' from PFI.");
+			goto err;
+		}
+		rc = pfi_header_getstring(pfi_header, "mode", mode,
+					  PFI_KEYWORD_LEN);
+		if (rc != 0) {
+			EBUF("Cannot read 'mode' from PFI.");
+			goto err;
+		}
+		if (strcmp(mode, "ubi") == 0) {
+			rc = read_pfi_ubi(pfi_header, fp_pfi, &ubi, label,
+					  err_buf, err_buf_size);
+			if (rc != 0) {
+				goto err;
+			}
+			*pfi_ubis = append_elem(ubi, *pfi_ubis);
+		}
+		else if (strcmp(mode, "raw") == 0) {
+			rc = read_pfi_raw(pfi_header, fp_pfi, &raw, label,
+					  err_buf, err_buf_size);
+			if (rc != 0) {
+				goto err;
+			}
+			*pfi_raws = append_elem(raw, *pfi_raws);
+		}
+		else {
+			EBUF("Recvieved unknown mode from PFI: %s", mode);
+			goto err;
+		}
+	}
+	goto out;
+
+ err:
+	*pfi_raws = remove_all((free_func_t)&free_pfi_raw, *pfi_raws);
+	*pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, *pfi_ubis);
+ out:
+	pfi_header_destroy(&pfi_header);
+	return rc;
+
+}
diff --git a/ubi-utils/old-utils/src/reader.h b/ubi-utils/old-utils/src/reader.h
new file mode 100644
index 0000000..715e464
--- /dev/null
+++ b/ubi-utils/old-utils/src/reader.h
@@ -0,0 +1,87 @@
+#ifndef __READER_H__
+#define __READER_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: Oliver Lohmann
+ *
+ * Read Platform Description Data (PDD).
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "pfi.h"
+#include "bootenv.h"
+#include "list.h"
+
+typedef enum flash_type_t {
+	NAND_FLASH = 0,
+	NOR_FLASH,
+} flash_type_t;
+
+typedef struct pdd_data *pdd_data_t;
+typedef struct pfi_raw	*pfi_raw_t;
+typedef struct pfi_ubi	*pfi_ubi_t;
+
+struct pdd_data {
+	uint32_t flash_size;
+	uint32_t flash_page_size;
+	uint32_t eb_size;
+	uint32_t vid_hdr_offset;
+	flash_type_t flash_type;
+};
+
+struct pfi_raw {
+	uint32_t data_size;
+	uint32_t *starts;
+	uint32_t starts_size;
+	uint32_t crc;
+};
+
+struct pfi_ubi {
+	uint32_t data_size;
+	uint32_t alignment;
+	uint32_t *ids;
+	uint32_t ids_size;
+	char	 **names;
+	uint32_t names_size;
+	uint32_t size;
+	enum { pfi_ubi_dynamic, pfi_ubi_static } type;
+	int curr_seqnum; /* specifies the seqnum taken in an update,
+			    default: 0 (used by pfiflash, ubimirror) */
+	uint32_t crc;
+};
+
+int read_pdd_data(FILE* fp_pdd, pdd_data_t *pdd_data,
+		char *err_buf, size_t err_buf_size);
+int read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi, pfi_raw_t *pfi_raw,
+		const char *label, char *err_buf, size_t err_buf_size);
+int read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi, pfi_ubi_t *pfi_ubi,
+		const char *label, char *err_buf, size_t err_buf_size);
+
+/**
+ * @brief Reads all pfi headers into list structures, separated by
+ *	  RAW and UBI sections.
+ */
+int read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi,
+		char* err_buf, size_t err_buf_size);
+int free_pdd_data(pdd_data_t *pdd_data);
+int free_pfi_raw(pfi_raw_t *raw_pfi);
+int free_pfi_ubi(pfi_ubi_t *pfi_ubi);
+
+#endif /* __READER_H__ */
diff --git a/ubi-utils/old-utils/src/ubigen.c b/ubi-utils/old-utils/src/ubigen.c
new file mode 100644
index 0000000..bb55fa9
--- /dev/null
+++ b/ubi-utils/old-utils/src/ubigen.c
@@ -0,0 +1,359 @@
+/*
+ * 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
+ *
+ * Tool to add UBI headers to binary images.
+ *
+ * 1.0 Initial version
+ * 1.1 Different CRC32 start value
+ * 1.2 Removed argp because we want to use uClibc.
+ * 1.3 Minor cleanups
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <mtd/ubi-media.h>
+
+#include "ubigen.h"
+#include "config.h"
+
+#define PROGRAM_VERSION "1.3"
+
+typedef enum action_t {
+	ACT_NORMAL	     = 0x00000001,
+	ACT_BROKEN_UPDATE    = 0x00000002,
+} action_t;
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+	"ubigen - a tool for adding UBI information to a binary input file.\n";
+
+static const char *optionsstr =
+" Common settings:\n"
+"  -c, --copyright            Print copyright information.\n"
+"  -d, --debug\n"
+"  -v, --verbose              Print more progress information.\n"
+"\n"
+" UBI Settings:\n"
+"  -A, --alignment=<num>      Set the alignment size to <num> (default 1).\n"
+"                             Values can be specified as bytes, 'ki' or 'Mi'.\n"
+"  -B, --blocksize=<num>      Set the eraseblock size to <num> (default 128\n"
+"                             KiB).\n"
+"                             Values can be specified as bytes, 'ki' or 'Mi'.\n"
+"  -E, --erasecount=<num>     Set the erase count to <num> (default 0)\n"
+"  -I, --id=<num>             The UBI volume id.\n"
+"  -O, --offset=<num>         Offset from start of an erase block to the UBI\n"
+"                             volume header.\n"
+"  -T, --type=<num>           The UBI volume type:\n"
+"                             1 = dynamic, 2 = static\n"
+"  -X, --setver=<num>         Set UBI version number to <num> (default 1)\n"
+"\n"
+" Input/Output:\n"
+"  -i, --infile=<filename>    Read input from file.\n"
+"  -o, --outfile=<filename>   Write output to file (default is stdout).\n"
+"\n"
+" Special options:\n"
+"  -U, --broken-update=<leb>  Create an ubi image which simulates a broken\n"
+"                             update.\n"
+"                             <leb> specifies the logical eraseblock number to\n"
+"                             update.\n"
+"\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: ubigen [-cdv?V] [-A <num>] [-B <num>] [-E <num>] [-I <num>]\n"
+"          [-O <num>] [-T <num>] [-X <num>] [-i <filename>] [-o <filename>]\n"
+"          [-U <leb>] [--copyright] [--debug] [--verbose] [--alignment=<num>]\n"
+"          [--blocksize=<num>] [--erasecount=<num>] [--id=<num>]\n"
+"          [--offset=<num>] [--type=<num>] [--setver=<num>]\n"
+"          [--infile=<filename>] [--outfile=<filename>]\n"
+"          [--broken-update=<leb>] [--help] [--usage] [--version]\n";
+
+struct option long_options[] = {
+	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
+	{ .name = "debug", .has_arg = 0, .flag = NULL, .val = 'd' },
+	{ .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'A' },
+	{ .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'B' },
+	{ .name = "erasecount", .has_arg = 1, .flag = NULL, .val = 'E' },
+	{ .name = "id", .has_arg = 1, .flag = NULL, .val = 'I' },
+	{ .name = "offset", .has_arg = 1, .flag = NULL, .val = 'O' },
+	{ .name = "type", .has_arg = 1, .flag = NULL, .val = 'T' },
+	{ .name = "setver", .has_arg = 1, .flag = NULL, .val = 'X' },
+	{ .name = "infile", .has_arg = 1, .flag = NULL, .val = 'i' },
+	{ .name = "outfile", .has_arg = 1, .flag = NULL, .val = 'o' },
+	{ .name = "broken-update", .has_arg = 1, .flag = NULL, .val = 'U' },
+	{ .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}
+};
+
+static const char copyright [] __attribute__((unused)) =
+	"Copyright IBM Corp 2006";
+
+#define CHECK_ENDP(option, endp) do {			\
+	if (*endp) {					\
+		fprintf(stderr,				\
+			"Parse error option \'%s\'. "	\
+			"No correct numeric value.\n"	\
+			, option);			\
+		exit(EXIT_FAILURE);			\
+	}						\
+} while(0)
+
+typedef struct myargs {
+	/* common settings */
+	action_t action;
+	int verbose;
+
+	int32_t id;
+	uint8_t type;
+	uint32_t eb_size;
+	uint64_t ec;
+	uint8_t version;
+	uint32_t hdr_offset;
+	uint32_t update_block;
+	uint32_t alignment;
+
+	FILE* fp_in;
+	FILE* fp_out;
+
+	/* special stuff needed to get additional arguments */
+	char *arg1;
+	char **options;			/* [STRING...] */
+} myargs;
+
+
+static int ustrtoul(const char *cp, char **endp, unsigned int base)
+{
+	unsigned long result = strtoul(cp, endp, base);
+
+	switch (**endp) {
+	case 'G':
+		result *= 1024;
+	case 'M':
+		result *= 1024;
+	case 'k':
+	case 'K':
+		result *= 1024;
+	/* "Ki", "ki", "Mi" or "Gi" are to be used. */
+		if ((*endp)[1] == 'i')
+			(*endp) += 2;
+	}
+	return result;
+}
+
+static int
+parse_opt(int argc, char **argv, myargs *args)
+{
+	int err = 0;
+	char* endp;
+
+	while (1) {
+		int key;
+
+		key = getopt_long(argc, argv, "cdvA:B:E:I:O:T:X:i:o:U:?V",
+				long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+			case 'c':
+				fprintf(stderr, "%s\n", copyright);
+				exit(0);
+				break;
+			case 'o': /* output */
+				args->fp_out = fopen(optarg, "wb");
+				if ((args->fp_out) == NULL) {
+					fprintf(stderr, "Cannot open file %s "
+						"for output\n", optarg);
+					exit(1);
+				}
+				break;
+			case 'i': /* input */
+				args->fp_in = fopen(optarg, "rb");
+				if ((args->fp_in) == NULL) {
+					fprintf(stderr, "Cannot open file %s "
+						"for input\n", optarg);
+					exit(1);
+				}
+				break;
+			case 'v': /* verbose */
+				args->verbose = 1;
+				break;
+
+			case 'B': /* eb_size */
+				args->eb_size =
+					(uint32_t)ustrtoul(optarg, &endp, 0);
+				CHECK_ENDP("B", endp);
+				break;
+			case 'E': /* erasecount */
+				args->ec = (uint64_t)strtoul(optarg, &endp, 0);
+				CHECK_ENDP("E", endp);
+				break;
+			case 'I': /* id */
+				args->id = (uint16_t)strtoul(optarg, &endp, 0);
+				CHECK_ENDP("I", endp);
+				break;
+			case 'T': /* type */
+				args->type =
+					(uint16_t)strtoul(optarg, &endp, 0);
+				CHECK_ENDP("T", endp);
+				break;
+			case 'X': /* versionnr */
+				args->version =
+					(uint8_t)strtoul(optarg, &endp, 0);
+				CHECK_ENDP("X", endp);
+				break;
+			case 'O': /* offset for volume hdr */
+				args->hdr_offset =
+					(uint32_t) strtoul(optarg, &endp, 0);
+				CHECK_ENDP("O", endp);
+				break;
+
+			case 'U': /* broken update */
+				args->action = ACT_BROKEN_UPDATE;
+				args->update_block =
+					(uint32_t) strtoul(optarg, &endp, 0);
+				CHECK_ENDP("U", endp);
+				break;
+
+			case '?': /* help */
+				fprintf(stderr, "Usage: ubigen [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);
+		}
+	}
+
+	if (optind < argc) {
+		if (!args->fp_in) {
+			args->fp_in = fopen(argv[optind++], "rb");
+			if ((args->fp_in) == NULL) {
+				fprintf(stderr,	"Cannot open file %s for "
+					"input\n", argv[optind]);
+				exit(1);
+			}
+		}
+	}
+	if (args->id < 0) {
+		err = 1;
+		fprintf(stderr,
+				"Please specify an UBI Volume ID.\n");
+	}
+	if (args->type == 0) {
+		err = 1;
+		fprintf(stderr,
+				"Please specify an UBI Volume type.\n");
+	}
+	if (err) {
+		fprintf(stderr, "%s", usage);
+		exit(1);
+	}
+
+	return 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+	int rc = 0;
+	ubi_info_t u;
+	struct stat file_info;
+	off_t input_len = 0; /* only used in static volumes */
+
+	myargs args = {
+		.action = ACT_NORMAL,
+		.verbose = 0,
+
+		.id = -1,
+		.type = 0,
+		.eb_size = 0,
+		.update_block = 0,
+		.ec = 0,
+		.version = 0,
+		.hdr_offset = (DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE),
+		.alignment = 1,
+
+		.fp_in = NULL,
+		.fp_out = stdout,
+		/* arguments */
+		.arg1 = NULL,
+		.options = NULL,
+	};
+
+	ubigen_init(); /* Init CRC32 table in ubigen */
+
+	/* parse arguments */
+	parse_opt(argc, argv, &args);
+
+	if (fstat(fileno(args.fp_in), &file_info) != 0) {
+		fprintf(stderr, "Cannot fetch file size "
+				"from input file.\n");
+	}
+	input_len = file_info.st_size;
+
+	rc = ubigen_create(&u, (uint32_t)args.id, args.type,
+			args.eb_size, args.ec, args.alignment,
+			args.version, args.hdr_offset, 0 ,input_len,
+			args.fp_in, args.fp_out);
+
+	if  (rc != 0) {
+		fprintf(stderr, "Cannot create UBI info handler rc: %d\n", rc);
+		exit(EXIT_FAILURE);
+	}
+
+	if (!args.fp_in || !args.fp_out) {
+		fprintf(stderr, "Input/Output error.\n");
+		exit(EXIT_FAILURE);
+
+	}
+
+	if (args.action & ACT_NORMAL) {
+		rc = ubigen_write_complete(u);
+	}
+	else if (args.action & ACT_BROKEN_UPDATE) {
+		rc = ubigen_write_broken_update(u, args.update_block);
+	}
+	if  (rc != 0) {
+		fprintf(stderr, "Error converting input data.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	rc = ubigen_destroy(&u);
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/ubigen.h b/ubi-utils/old-utils/src/ubigen.h
new file mode 100644
index 0000000..8d29120
--- /dev/null
+++ b/ubi-utils/old-utils/src/ubigen.h
@@ -0,0 +1,149 @@
+#ifndef __UBIGEN_H__
+#define __UBIGEN_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: Frank Haverkamp
+ *
+ * An utility to update UBI volumes.
+ */
+
+#include <stdio.h> /* FILE */
+#include <stdint.h>
+#include <mtd/ubi-media.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEFAULT_BLOCKSIZE	(128 * 1024)
+#define DEFAULT_PAGESIZE	(2*1024)
+
+#define EUBIGEN_INVALID_TYPE		1
+#define EUBIGEN_INVALID_HDR_OFFSET	2
+#define EUBIGEN_INVALID_ALIGNMENT	3
+#define EUBIGEN_TOO_SMALL_EB		4
+#define EUBIGEN_MAX_ERROR		5
+
+
+typedef enum action {
+	NO_ERROR	 = 0x00000000,
+	BROKEN_HDR_CRC	 = 0x00000001,
+	BROKEN_DATA_CRC	 = 0x00000002,
+	BROKEN_DATA_SIZE = 0x00000004,
+	BROKEN_OMIT_BLK	 = 0x00000008,
+	MARK_AS_UPDATE	 = 0x00000010,
+} ubigen_action_t;
+
+typedef struct ubi_info *ubi_info_t;
+
+/**
+ * @brief	  Initialize the internal CRC32 table.
+ * @note	  Necessary because of the used crc32 function in UBI.
+ *		  A usage of CRC32, from e.g. zlib will fail.
+ */
+void ubigen_init(void);
+
+/**
+ * @brief	  Create an ubigen handle.
+ * @param  ...
+ * @return 0	  On sucess.
+ *	   else	  Error.
+ * @note	  This parameterlist is ugly. But we have to use
+ *		  two big structs and meta information internally,
+ *		  filling them would be even uglier.
+ */
+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);
+
+/**
+ * @brief	  Destroy an ubigen handle.
+ * @param  u	  Handle to free.
+ * @return 0	  On success.
+ *	   else	  Error.
+ */
+int ubigen_destroy(ubi_info_t *u);
+
+/**
+ * @brief	  Get number of total logical EBs, necessary for the
+ *		  complete storage of data in the handle.
+ * @param  u	  The handle.
+ * @return 0	  On success.
+ *	   else	  Error.
+ */
+int ubigen_get_leb_total(ubi_info_t u, size_t* total);
+
+/**
+ * @brief	  Get the size in bytes of one logical EB in the handle.
+ * @param  u	  The handle.
+ * @return 0	  On success.
+ *	   else	  Error.
+ */
+int ubigen_get_leb_size(ubi_info_t u, size_t* size);
+
+
+/**
+ * @brief	  Write a logical EB (fits exactly into 1 physical EB).
+ * @param  u	  Handle which holds all necessary data.
+ * @param  action Additional operations which shall be applied on this
+ *		  logical eraseblock. Mostly injecting artifical errors.
+ * @return 0	  On success.
+ *	   else	  Error.
+ */
+int ubigen_write_leb(ubi_info_t u, ubigen_action_t action);
+
+/**
+ * @brief	  Write a complete array of logical eraseblocks at once.
+ * @param  u	  Handle which holds all necessary data.
+ * @return 0	  On success.
+ *	   else	  Error.
+ */
+int ubigen_write_complete(ubi_info_t u);
+
+/**
+ * @brief	  Write a single block which is extracted from the
+ *		  binary input data.
+ * @param  u	  Handle which holds all necessary data.
+ * @param  blk	  Logical eraseblock which shall hold a inc. copy entry
+ *		  and a bad data crc.
+ * @return 0	  On success.
+ *	   else	  Error.
+ */
+int ubigen_write_broken_update(ubi_info_t u, uint32_t blk);
+
+/**
+ * @brief	  Use the current ubi_info data and some additional data
+ *		  to set an UBI volume table entry from it.
+ * @param  u	  Handle which holds some of the necessary data.
+ * @param  res_bytes Number of reserved bytes which is stored in the volume
+ *		     table entry.
+ * @param  name	   A string which shall be used as a volume label.
+ * @param  lvol_r  A pointer to a volume table entry.
+ * @return 0	   On success.
+ *	   else	   Error.
+ */
+int ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes,
+		const char* name, struct ubi_vtbl_record *lvol_rec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UBIGEN_H__ */
diff --git a/ubi-utils/old-utils/src/ubimirror.c b/ubi-utils/old-utils/src/ubimirror.c
new file mode 100644
index 0000000..da05a8b
--- /dev/null
+++ b/ubi-utils/old-utils/src/ubimirror.c
@@ -0,0 +1,213 @@
+/*
+ * 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
+ *
+ * 1.2 Removed argp because we want to use uClibc.
+ * 1.3 Minor cleanups
+ * 1.4 Migrated to new libubi
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <errno.h>
+#include <mtd/ubi-media.h>
+
+#include "config.h"
+#include "error.h"
+#include "example_ubi.h"
+#include "ubimirror.h"
+
+#define PROGRAM_VERSION "1.4"
+
+typedef enum action_t {
+	ACT_NORMAL = 0,
+	ACT_ARGP_ABORT,
+	ACT_ARGP_ERR,
+} action_t;
+
+#define ABORT_ARGP do {			\
+	args->action = ACT_ARGP_ABORT;	\
+} while (0)
+
+#define ERR_ARGP do {			\
+	args->action = ACT_ARGP_ERR;	\
+} while (0)
+
+#define VOL_ARGS_MAX 2
+
+static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
+	"ubimirror - mirrors ubi volumes.\n";
+
+static const char *optionsstr =
+"  -c, --copyright            Print copyright information.\n"
+"  -s, --side=<seqnum>        Use the side <seqnum> as source.\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: ubimirror [-c?V] [-s <seqnum>] [--copyright] [--side=<seqnum>]\n"
+"            [--help] [--usage] [--version] <source> <destination>\n";
+
+static const char copyright [] __attribute__((unused)) =
+	"(C) IBM Coorporation 2007";
+
+struct option long_options[] = {
+	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
+	{ .name = "side", .has_arg = 1, .flag = NULL, .val = 's' },
+	{ .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}
+};
+
+typedef struct myargs {
+	action_t action;
+	int side;
+	int vol_no;			/* index of current volume */
+	/* @FIXME replace by bootenv_list, makes live easier */
+	/* @FIXME remove the constraint of two entries in the array */
+	const char* vol[VOL_ARGS_MAX];	/* comma separated list of src/dst
+					   volumes */
+	char *arg1;
+	char **options;		/* [STRING...] */
+} myargs;
+
+static int
+get_update_side(const char* str)
+{
+	uint32_t i = strtoul(str, NULL, 0);
+
+	if ((i != 0) && (i != 1)) {
+		return -1;
+	}
+	return i;
+}
+
+
+static int
+parse_opt(int argc, char **argv, myargs *args)
+{
+	while (1) {
+		int key;
+
+		key = getopt_long(argc, argv, "cs:?V", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+			case 'c':
+				err_msg("%s", copyright);
+				ABORT_ARGP;
+				break;
+			case 's':
+				args->side = get_update_side(optarg);
+				if (args->side < 0) {
+					err_msg("Unsupported seqnum: %s.\n"
+						"Supported seqnums are '0' "
+						"and '1'\n", optarg);
+					ERR_ARGP;
+				}
+				break;
+			case '?': /* help */
+				err_msg("Usage: ubimirror [OPTION...] "
+					"<source> <destination>\n");
+				err_msg("%s", doc);
+				err_msg("%s", optionsstr);
+				err_msg("\nReport bugs to %s\n",
+					PACKAGE_BUGREPORT);
+				exit(0);
+				break;
+			case 'V':
+				err_msg("%s", PROGRAM_VERSION);
+				exit(0);
+				break;
+			default:
+				err_msg("%s", usage);
+				exit(-1);
+			}
+	}
+
+	while (optind < argc) {
+		/* only two entries allowed */
+		if (args->vol_no >= VOL_ARGS_MAX) {
+			err_msg("%s", usage);
+			ERR_ARGP;
+		}
+		args->vol[(args->vol_no)++] = argv[optind++];
+	}
+
+	return 0;
+}
+
+
+int
+main(int argc, char **argv) {
+	int rc = 0;
+	unsigned int ids[VOL_ARGS_MAX];
+	char err_buf[1024];
+
+	myargs args = {
+		.action = ACT_NORMAL,
+		.side = -1,
+		.vol_no = 0,
+		.vol = {"", ""},
+		.options = NULL,
+	};
+
+	parse_opt(argc, argv, &args);
+	if (args.action == ACT_ARGP_ERR) {
+		rc = 127;
+		goto err;
+	}
+	if (args.action == ACT_ARGP_ABORT) {
+		rc = 126;
+		goto out;
+	}
+	if (args.vol_no < VOL_ARGS_MAX) {
+		fprintf(stderr, "missing volume number for %s\n",
+			args.vol_no == 0 ? "source and target" : "target");
+		rc = 125;
+		goto out;
+	}
+	for( rc = 0; rc < args.vol_no; ++rc){
+		char *endp;
+		ids[rc] = strtoul(args.vol[rc], &endp, 0);
+		if( *endp != '\0' ){
+			fprintf(stderr, "invalid volume number %s\n",
+					args.vol[rc]);
+			rc = 125;
+			goto out;
+		}
+	}
+	rc = ubimirror(EXAMPLE_UBI_DEVICE, args.side, ids, args.vol_no,
+		       err_buf, sizeof(err_buf));
+	if( rc ){
+		err_buf[sizeof err_buf - 1] = '\0';
+		fprintf(stderr, "%s", err_buf);
+		if( rc < 0 )
+			rc = -rc;
+	}
+ out:
+ err:
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/ubimirror.h b/ubi-utils/old-utils/src/ubimirror.h
new file mode 100644
index 0000000..d7ae2ad
--- /dev/null
+++ b/ubi-utils/old-utils/src/ubimirror.h
@@ -0,0 +1,66 @@
+#ifndef __UBIMIRROR_H__
+#define __UBIMIRROR_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: Oliver Lohmann
+ *
+ * An utility to mirror UBI volumes.
+ */
+
+#include <stdint.h>
+
+/**
+ * @def EUBIMIRROR_SRC_EQ_DST
+ *	@brief Given source volume is also in the set of destination volumes.
+ */
+#define EUBIMIRROR_SRC_EQ_DST	20
+
+/**
+ * @def EUBIMIRROR_NO_SRC
+ *	@brief The given source volume does not exist.
+ */
+#define EUBIMIRROR_NO_SRC	21
+
+/**
+ * @def EUBIMIRROR_NO_DST
+ *	@brief One of the given destination volumes does not exist.
+ */
+#define EUBIMIRROR_NO_DST	22
+
+/**
+ * @brief Mirrors UBI devices from a source device (specified by seqnum)
+ *	  to n target devices.
+ * @param devno Device number used by the UBI operations.
+ * @param seqnum An index into ids (defines the src_id).
+ * @param ids An array of ids.
+ * @param ids_size The number of entries in the ids array.
+ * @param err_buf A buffer to store verbose error messages.
+ * @param err_buf_size The size of the error buffer.
+ *
+ * @note A seqnum of value < 0 defaults to a seqnum of 0.
+ * @note A seqnum exceeding the range of ids_size defaults to 0.
+ * @note An empty ids list results in a empty stmt.
+ * @pre	The UBI volume which shall be used as source volume exists.
+ * @pre	The UBI volumes which are defined as destination volumes exist.
+ * @post The content of the UBI volume which was defined as source volume
+ *	 equals the content of the volumes which were defined as destination.
+ */
+int ubimirror(uint32_t devno, int seqnum, uint32_t* ids, ssize_t ids_size,
+	      char *err_buf, size_t err_buf_size);
+
+#endif /* __UBIMIRROR_H__ */
diff --git a/ubi-utils/old-utils/src/unubi.c b/ubi-utils/old-utils/src/unubi.c
new file mode 100644
index 0000000..0f72b18
--- /dev/null
+++ b/ubi-utils/old-utils/src/unubi.c
@@ -0,0 +1,1024 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006, 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.
+ */
+
+/*
+ * Authors: Drake Dowsett, dowsett@de.ibm.com
+ *          Frank Haverkamp, haver@vnet.ibm.com
+ *
+ * 1.2 Removed argp because we want to use uClibc.
+ * 1.3 Minor cleanups.
+ * 1.4 Meanwhile Drake had done a lot of changes, syncing those.
+ * 1.5 Bugfixes, simplifications
+ */
+
+/*
+ * unubi  reads  an  image  file containing blocks of UBI headers and data
+ * (such as produced from nand2bin) and rebuilds the volumes within.   The
+ * default  operation  (when  no  flags are given) is to rebuild all valid
+ * volumes found in the image. unubi  can  also  read  straight  from  the
+ * onboard MTD device (ex. /dev/mtdblock/NAND).
+ */
+
+/* TODO: consideration for dynamic vs. static volumes */
+
+#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 <limits.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <mtd/ubi-media.h>
+#include <mtd_swab.h>
+
+#include "crc32.h"
+#include "unubi_analyze.h"
+
+#define EXEC		"unubi"
+#define CONTACT		"haver@vnet.ibm.com"
+#define VERSION		"1.5"
+
+static char doc[] = "\nVersion: " VERSION "\n";
+static int debug = 0;
+
+static const char *optionsstr =
+"Extract volumes and/or analysis information from an UBI data file.\n"
+"When no parameters are flagged or given, the default operation is\n"
+"to rebuild all valid complete UBI volumes found within the image.\n"
+"\n"
+" OPERATIONS\n"
+"  -a, --analyze              Analyze image and create gnuplot graphs\n"
+"  -i, --info-table           Extract volume information tables\n"
+"  -r, --rebuild=<volume-id>  Extract and rebuild volume\n"
+"\n"
+" OPTIONS\n"
+"  -b, --blocksize=<block-size>   Specify size of eraseblocks in image in bytes\n"
+"                             (default 128KiB)\n"
+"  -d, --dir=<output-dir>     Specify output directory\n"
+"  -D, --debug                Enable debug output\n"
+"  -s, --headersize=<header-size>   Specify size reserved for metadata in eraseblock\n"
+	"                             in bytes (default 2048 Byte)\n"
+ /* the -s option might be insufficient when using different vid
+    offset than what we used when writing this tool ... Better would
+    probably be --vid-hdr-offset or alike */
+"\n"
+" ADVANCED\n"
+"  -e, --eb-split             Generate individual eraseblock images (all\n"
+"                             eraseblocks)\n"
+"  -v, --vol-split            Generate individual eraseblock images (valid\n"
+"                             eraseblocks only)\n"
+"  -V, --vol-split!           Raw split by eraseblock (valid eraseblocks only)\n"
+"\n"
+"  -?, --help                 Give this help list\n"
+"      --usage                Give a short usage message\n"
+"      --version              Print program version\n"
+"\n";
+
+static const char *usage =
+"Usage: unubi [-aievV?] [-r <volume-id>] [-b <block-size>] [-d <output-dir>]\n"
+"            [-s <header-size>] [--analyze] [--info-table]\n"
+"            [--rebuild=<volume-id>] [--blocksize=<block-size>]\n"
+"            [--dir=<output-dir>] [--headersize=<header-size>] [--eb-split]\n"
+"            [--vol-split] [--vol-split!] [--help] [--usage] [--version]\n"
+"            image-file\n";
+
+#define ERR_MSG(fmt...)							\
+	fprintf(stderr, EXEC ": " fmt)
+
+#define SPLIT_DATA	1
+#define SPLIT_RAW	2
+
+#define DIR_FMT		"unubi_%s"
+#define KIB		1024
+#define MIB		(KIB * KIB)
+#define MAXPATH		KIB
+
+/* filenames */
+#define FN_INVAL	"%s/eb%04u%s"			/* invalid eraseblock */
+#define FN_NSURE	"%s/eb%04u_%03u_%03u_%03x%s"	/* unsure eraseblock */
+#define FN_VALID	"%s/eb%04u_%03u_%03u_%03x%s"	/* valid eraseblock */
+#define FN_VOLSP	"%s/vol%03u_%03u_%03u_%04zu"	/* split volume */
+#define FN_VOLWH	"%s/volume%03u"			/* whole volume */
+#define FN_VITBL	"%s/vol_info_table%zu"		/* vol info table */
+
+static uint32_t crc32_table[256];
+
+/* struct args:
+ *	bsize		int, blocksize of image blocks
+ *	hsize		int, eraseblock header size
+ *	analyze		flag, when non-zero produce analysis
+ *	eb_split	flag, when non-zero output eb####
+ *			note: SPLIT_DATA vs. SPLIT_RAW
+ *	vol_split	flag, when non-zero output vol###_####
+ *			note: SPLIT_DATA vs. SPLIT_RAW
+ *	odir_path	string, directory to place volumes in
+ *	img_path	string, file to read as ubi image
+ *	vols		int array of size UBI_MAX_VOLUMES, where a 1 can be
+ *			written for each --rebuild flag in the index specified
+ *			then the array can be counted and collapsed using
+ *			count_set() and collapse()
+ */
+struct args {
+	int analyze;
+	int itable;
+	uint32_t *vols;
+
+	size_t vid_hdr_offset;
+	size_t data_offset;
+	size_t bsize;		/* FIXME replace by vid_hdr/data offs? */
+	size_t hsize;
+
+	char *odir_path;
+	int eb_split;
+	int vol_split;
+	char *img_path;
+
+	char **options;
+};
+
+struct option long_options[] = {
+	{ .name = "rebuild", .has_arg = 1, .flag = NULL, .val = 'r' },
+	{ .name = "dir", .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ .name = "analyze", .has_arg = 0, .flag = NULL, .val = 'a' },
+	{ .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'b' },
+	{ .name = "eb-split", .has_arg = 0, .flag = NULL, .val = 'e' },
+	{ .name = "vol-split", .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "vol-split!", .has_arg = 0, .flag = NULL, .val = 'e' },
+	{ .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 = 'J' },
+	{ NULL, 0, NULL, 0}
+};
+
+/**
+ * parses out a numerical value from a string of numbers followed by:
+ *	k, K, kib, KiB for kibibyte
+ *	m, M, mib, MiB for mebibyte
+ **/
+static uint32_t
+str_to_num(char *str)
+{
+	char *s;
+	ulong num;
+
+	s = str;
+	num = strtoul(s, &s, 0);
+
+	if (*s != '\0') {
+		if ((strcmp(s, "KiB") == 0) || (strcmp(s, "K") == 0) ||
+		    (strcmp(s, "kib") == 0) || (strcmp(s, "k") == 0))
+			num *= KIB;
+		else if ((strcmp(s, "MiB") == 0) || (strcmp(s, "M") == 0) ||
+		    (strcmp(s, "mib") == 0) || (strcmp(s, "m") == 0))
+			num *= MIB;
+		else
+			ERR_MSG("couldn't parse '%s', assuming %lu\n",
+				s, num);
+	}
+	return num;
+}
+
+static int
+parse_opt(int argc, char **argv, struct args *args)
+{
+	uint32_t i;
+
+	while (1) {
+		int key;
+
+		key = getopt_long(argc, argv, "ab:s:d:Deir:vV?J",
+				  long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'a': /* --analyze */
+			args->analyze = 1;
+			break;
+		case 'b': /* --block-size=<block-size> */
+			args->bsize = str_to_num(optarg);
+			break;
+		case 's': /* --header-size=<header-size> */
+			args->hsize = str_to_num(optarg);
+			break;
+		case 'd': /* --dir=<output-dir> */
+			args->odir_path = optarg;
+			break;
+		case 'D': /* --debug */
+			/* I wanted to use -v but that was already
+			   used ... */
+			debug = 1;
+			break;
+		case 'e': /* --eb-split */
+			args->eb_split = SPLIT_RAW;
+			break;
+		case 'i': /* --info-table */
+			args->itable = 1;
+			break;
+		case 'r': /* --rebuild=<volume-id> */
+			i = str_to_num(optarg);
+			if (i < UBI_MAX_VOLUMES)
+				args->vols[str_to_num(optarg)] = 1;
+			else {
+				ERR_MSG("volume-id out of bounds\n");
+				return -1;
+			}
+			break;
+		case 'v': /* --vol-split */
+			if (args->vol_split != SPLIT_RAW)
+				args->vol_split = SPLIT_DATA;
+			break;
+		case 'V': /* --vol-split! */
+			args->vol_split = SPLIT_RAW;
+			break;
+		case '?': /* help */
+			fprintf(stderr,	"Usage: unubi [OPTION...] "
+				"image-file\n%s%s\nReport bugs to %s\n",
+				doc, optionsstr, CONTACT);
+			exit(0);
+			break;
+		case 'J':
+			fprintf(stderr, "%s\n", VERSION);
+			exit(0);
+			break;
+		default:
+			fprintf(stderr, "%s", usage);
+			exit(-1);
+		}
+	}
+
+	/* FIXME I suppose hsize should be replaced! */
+	args->vid_hdr_offset = args->hsize - UBI_VID_HDR_SIZE;
+	args->data_offset = args->hsize;
+
+	if (optind < argc)
+		args->img_path = argv[optind++];
+	return 0;
+}
+
+
+/**
+ * counts the number of indicies which are flagged in full_array;
+ * full_array is an array of flags (1/0);
+ **/
+static size_t
+count_set(uint32_t *full_array, size_t full_len)
+{
+	size_t count, i;
+
+	if (full_array == NULL)
+		return 0;
+
+	for (i = 0, count = 0; i < full_len; i++)
+		if (full_array[i] != 0)
+			count++;
+
+	return count;
+}
+
+
+/**
+ * generates coll_array from full_array;
+ * full_array is an array of flags (1/0);
+ * coll_array is an array of the indicies in full_array which are flagged (1);
+ **/
+static size_t
+collapse(uint32_t *full_array, size_t full_len,
+	 uint32_t *coll_array, size_t coll_len)
+{
+	size_t i, j;
+
+	if ((full_array == NULL) || (coll_array == NULL))
+		return 0;
+
+	for (i = 0, j = 0; (i < full_len) && (j < coll_len); i++)
+		if (full_array[i] != 0) {
+			coll_array[j] = i;
+			j++;
+		}
+
+	return j;
+}
+
+/**
+ * data_crc: save the FILE* position, calculate the crc over a span,
+ *	reset the position
+ * returns non-zero when EOF encountered
+ **/
+static int
+data_crc(FILE* fpin, size_t length, uint32_t *ret_crc)
+{
+	int rc;
+	size_t i;
+	char buf[length];
+	uint32_t crc;
+	fpos_t start;
+
+	rc = fgetpos(fpin, &start);
+	if (rc < 0)
+		return -1;
+
+	for (i = 0; i < length; i++) {
+		int c = fgetc(fpin);
+		if (c == EOF) {
+			ERR_MSG("unexpected EOF\n");
+			return -1;
+		}
+		buf[i] = (char)c;
+	}
+
+	rc = fsetpos(fpin, &start);
+	if (rc < 0)
+		return -1;
+
+	crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, length);
+	*ret_crc = crc;
+	return 0;
+}
+
+
+/**
+ * reads data of size len from fpin and writes it to path
+ **/
+static int
+extract_data(FILE* fpin, size_t len, const char *path)
+{
+	int rc;
+	size_t i;
+	FILE* fpout;
+
+	rc = 0;
+	fpout = NULL;
+
+	fpout = fopen(path, "wb");
+	if (fpout == NULL) {
+		ERR_MSG("couldn't open file for writing: %s\n", path);
+		rc = -1;
+		goto err;
+	}
+
+	for (i = 0; i < len; i++) {
+		int c = fgetc(fpin);
+		if (c == EOF) {
+			ERR_MSG("unexpected EOF while writing: %s\n", path);
+			rc = -2;
+			goto err;
+		}
+		c = fputc(c, fpout);
+		if (c == EOF) {
+			ERR_MSG("couldn't write: %s\n", path);
+			rc = -3;
+			goto err;
+		}
+	}
+
+ err:
+	if (fpout != NULL)
+		fclose(fpout);
+	return rc;
+}
+
+
+/**
+ * extract volume information table from block. saves and reloads fpin
+ * position
+ * returns -1 when a fpos set or get fails, otherwise <= -2 on other
+ * failure and 0 on success
+ **/
+static int
+extract_itable(FILE *fpin, struct eb_info *cur, size_t bsize, size_t num,
+	       const char *path)
+{
+	char filename[MAXPATH + 1];
+	int rc;
+	size_t i, max;
+	fpos_t temp;
+	FILE* fpout = NULL;
+	struct ubi_vtbl_record rec;
+
+	if (fpin == NULL || cur == NULL || path == NULL)
+		return -2;
+
+	/* remember position */
+	rc = fgetpos(fpin, &temp);
+	if (rc < 0)
+		return -1;
+
+	/* jump to top of eraseblock, skip to data section */
+	fsetpos(fpin, &cur->eb_top);
+	if (rc < 0)
+		return -1;
+	fseek(fpin, be32_to_cpu(cur->ec.data_offset), SEEK_CUR);
+
+	/* prepare output file */
+	if (be32_to_cpu(cur->vid.vol_id) != UBI_LAYOUT_VOLUME_ID)
+		return -2;
+	memset(filename, 0, MAXPATH + 1);
+	snprintf(filename, MAXPATH, FN_VITBL, path, num);
+	fpout = fopen(filename, "w");
+	if (fpout == NULL)
+		return -2;
+
+	/* loop through entries */
+	fprintf(fpout,
+		"index\trpebs\talign\ttype\tcrc\t\tname\n");
+	max = bsize - be32_to_cpu(cur->ec.data_offset);
+	for (i = 0; i < (max / sizeof(rec)); i++) {
+		int blank = 1;
+		char *ptr, *base;
+		char name[UBI_VOL_NAME_MAX + 1];
+		const char *type = "unknown\0";
+		uint32_t crc;
+
+		/* read record */
+		rc = fread(&rec, 1, sizeof(rec), fpin);
+		if (rc == 0)
+			break;
+		if (rc != sizeof(rec)) {
+			ERR_MSG("reading volume information "
+				"table record failed\n");
+			rc = -3;
+			goto exit;
+		}
+
+		/* check crc */
+		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &rec,
+				UBI_VTBL_RECORD_SIZE_CRC);
+		if (crc != be32_to_cpu(rec.crc))
+			continue;
+
+		/* check for empty */
+		base = (char *)&rec;
+		ptr = base;
+		while (blank &&
+		       ((unsigned)(ptr - base) < UBI_VTBL_RECORD_SIZE_CRC)) {
+			if (*ptr != 0)
+				blank = 0;
+			ptr++;
+		}
+
+		if (blank)
+			continue;
+
+		/* prep type string */
+		if (rec.vol_type == UBI_VID_DYNAMIC)
+			type = "dynamic\0";
+		else if (rec.vol_type == UBI_VID_STATIC)
+			type = "static\0";
+
+		/* prep name string */
+		rec.name[be16_to_cpu(rec.name_len)] = '\0';
+		sprintf(name, "%s", rec.name);
+
+		/* print record line to fpout */
+		fprintf(fpout, "%zu\t%u\t%u\t%s\t0x%08x\t%s\n",
+			i,
+			be32_to_cpu(rec.reserved_pebs),
+			be32_to_cpu(rec.alignment),
+			type,
+			be32_to_cpu(rec.crc),
+			name);
+	}
+
+ exit:
+	/* reset position */
+	if (fsetpos(fpin, &temp) < 0)
+		rc = -1;
+
+	if (fpout != NULL)
+		fclose(fpout);
+
+	return rc;
+}
+
+
+/**
+ * using eb chain, tries to rebuild the data of volume at vol_id, or for all
+ * the known volumes, if vol_id is NULL;
+ **/
+static int
+rebuild_volume(FILE * fpin, uint32_t *vol_id, struct eb_info **head,
+	       const char *path, size_t block_size, size_t header_size)
+{
+	char filename[MAXPATH];
+	int rc;
+	uint32_t vol, num, data_size;
+	FILE* fpout;
+	struct eb_info *cur;
+
+	rc = 0;
+
+	if ((fpin == NULL) || (head == NULL) || (*head == NULL))
+		return 0;
+
+	/* when vol_id is null, then do all  */
+	if (vol_id == NULL) {
+		cur = *head;
+		vol = be32_to_cpu(cur->vid.vol_id);
+	} else {
+		vol = *vol_id;
+		eb_chain_position(head, vol, NULL, &cur);
+		if (cur == NULL) {
+			if (debug)
+				ERR_MSG("no valid volume %d was found\n", vol);
+			return -1;
+		}
+	}
+
+	num = 0;
+	snprintf(filename, MAXPATH, FN_VOLWH, path, vol);
+	fpout = fopen(filename, "wb");
+	if (fpout == NULL) {
+		ERR_MSG("couldn't open file for writing: %s\n", filename);
+		return -1;
+	}
+
+	while (cur != NULL) {
+		size_t i;
+
+		if (be32_to_cpu(cur->vid.vol_id) != vol) {
+			/* close out file */
+			fclose(fpout);
+
+			/* only stay around if that was the only volume */
+			if (vol_id != NULL)
+				goto out;
+
+			/* begin with next */
+			vol = be32_to_cpu(cur->vid.vol_id);
+			num = 0;
+			snprintf(filename, MAXPATH, FN_VOLWH, path, vol);
+			fpout = fopen(filename, "wb");
+			if (fpout == NULL) {
+				ERR_MSG("couldn't open file for writing: %s\n",
+					filename);
+				return -1;
+			}
+		}
+
+		while (num < be32_to_cpu(cur->vid.lnum)) {
+			/* FIXME haver: I hope an empty block is
+			   written out so that the binary has no holes
+			   ... */
+			if (debug)
+				ERR_MSG("missing valid block %d for volume %d\n",
+					num, vol);
+			num++;
+		}
+
+		rc = fsetpos(fpin, &(cur->eb_top));
+		if (rc < 0)
+			goto out;
+		fseek(fpin, be32_to_cpu(cur->ec.data_offset), SEEK_CUR);
+
+		if (cur->vid.vol_type == UBI_VID_DYNAMIC)
+			/* FIXME It might be that alignment has influence */
+			data_size = block_size - header_size;
+		else
+			data_size = be32_to_cpu(cur->vid.data_size);
+
+		for (i = 0; i < data_size; i++) {
+			int c = fgetc(fpin);
+			if (c == EOF) {
+				ERR_MSG("unexpected EOF while writing: %s\n",
+					filename);
+				rc = -2;
+				goto out;
+			}
+			c = fputc(c, fpout);
+			if (c == EOF) {
+				ERR_MSG("couldn't write: %s\n", filename);
+				rc = -3;
+				goto out;
+			}
+		}
+
+		cur = cur->next;
+		num++;
+	}
+
+ out:
+	if (vol_id == NULL)
+		fclose(fpout);
+	return rc;
+}
+
+
+/**
+ * traverses FILE* trying to load complete, valid and accurate header data
+ * into the eb chain;
+ **/
+static int
+unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
+{
+	char filename[MAXPATH + 1];
+	char reason[MAXPATH + 1];
+	int rc;
+	size_t i, count, itable_num;
+	/* relations:
+	 * cur ~ head
+	 * next ~ first */
+	struct eb_info *head, *cur, *first, *next;
+	struct eb_info **next_ptr;
+
+	rc = 0;
+	count = 0;
+	itable_num = 0;
+	head = NULL;
+	first = NULL;
+	next = NULL;
+	cur = malloc(sizeof(*cur));
+	if (cur == NULL) {
+		ERR_MSG("out of memory\n");
+		rc = -ENOMEM;
+		goto err;
+	}
+	memset(cur, 0, sizeof(*cur));
+
+	fgetpos(fpin, &(cur->eb_top));
+	while (1) {
+		const char *raw_path;
+		uint32_t crc;
+
+		cur->phys_addr = ftell(fpin);
+		cur->phys_block = cur->phys_addr / a->bsize;
+		cur->data_crc_ok = 0;
+		cur->ec_crc_ok   = 0;
+		cur->vid_crc_ok  = 0;
+
+		memset(filename, 0, MAXPATH + 1);
+		memset(reason, 0, MAXPATH + 1);
+
+		/* in case of an incomplete ec header */
+		raw_path = FN_INVAL;
+
+		/* read erasecounter header */
+		rc = fread(&cur->ec, 1, sizeof(cur->ec), fpin);
+		if (rc == 0)
+			goto out; /* EOF */
+		if (rc != sizeof(cur->ec)) {
+			ERR_MSG("reading ec-hdr failed\n");
+			rc = -1;
+			goto err;
+		}
+
+		/* check erasecounter header magic */
+		if (be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) {
+			snprintf(reason, MAXPATH, ".invalid.ec_magic");
+			goto invalid;
+		}
+
+		/* check erasecounter header crc */
+		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->ec),
+				UBI_EC_HDR_SIZE_CRC);
+		if (be32_to_cpu(cur->ec.hdr_crc) != crc) {
+			snprintf(reason, MAXPATH, ".invalid.ec_hdr_crc");
+			goto invalid;
+		}
+
+		/* read volume id header */
+		rc = fsetpos(fpin, &(cur->eb_top));
+		if (rc != 0)
+			goto err;
+		fseek(fpin, be32_to_cpu(cur->ec.vid_hdr_offset), SEEK_CUR);
+		rc = fread(&cur->vid, 1, sizeof(cur->vid), fpin);
+		if (rc == 0)
+			goto out; /* EOF */
+		if (rc != sizeof(cur->vid)) {
+			ERR_MSG("reading vid-hdr failed\n");
+			rc = -1;
+			goto err;
+		}
+
+		/* if the magic number is 0xFFFFFFFF, then it's very likely
+		 * that the volume is empty */
+		if (be32_to_cpu(cur->vid.magic) == 0xffffffff) {
+			snprintf(reason, MAXPATH, ".empty");
+			goto invalid;
+		}
+
+		/* vol_id should be in bounds */
+		if ((be32_to_cpu(cur->vid.vol_id) >= UBI_MAX_VOLUMES) &&
+		    (be32_to_cpu(cur->vid.vol_id) <
+		     UBI_INTERNAL_VOL_START)) {
+			snprintf(reason, MAXPATH, ".invalid");
+			goto invalid;
+		} else
+			raw_path = FN_NSURE;
+
+		/* check volume id header magic */
+		if (be32_to_cpu(cur->vid.magic) != UBI_VID_HDR_MAGIC) {
+			snprintf(reason, MAXPATH, ".invalid.vid_magic");
+			goto invalid;
+		}
+		cur->ec_crc_ok = 1;
+
+		/* check volume id header crc */
+		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->vid),
+				UBI_VID_HDR_SIZE_CRC);
+		if (be32_to_cpu(cur->vid.hdr_crc) != crc) {
+			snprintf(reason, MAXPATH, ".invalid.vid_hdr_crc");
+			goto invalid;
+		}
+		cur->vid_crc_ok = 1;
+
+		/* check data crc, but only for a static volume */
+		if (cur->vid.vol_type == UBI_VID_STATIC) {
+			rc = data_crc(fpin, be32_to_cpu(cur->vid.data_size),
+				      &crc);
+			if (rc < 0)
+				goto err;
+			if (be32_to_cpu(cur->vid.data_crc) != crc) {
+				snprintf(reason, MAXPATH, ".invalid.data_crc");
+				goto invalid;
+			}
+			cur->data_crc_ok = 1;
+		}
+
+		/* enlist this vol, it's valid */
+		raw_path = FN_VALID;
+		cur->linear = count;
+		rc = eb_chain_insert(&head, cur);
+		if (rc < 0) {
+			if (rc == -ENOMEM) {
+				ERR_MSG("out of memory\n");
+				goto err;
+			}
+			ERR_MSG("unknown and unexpected error, please contact "
+				CONTACT "\n");
+			goto err;
+		}
+
+		/* extract info-table */
+		if (a->itable &&
+		    (be32_to_cpu(cur->vid.vol_id) == UBI_LAYOUT_VOLUME_ID)) {
+			extract_itable(fpin, cur, a->bsize,
+				       itable_num, a->odir_path);
+			itable_num++;
+		}
+
+		/* split volumes */
+		if (a->vol_split) {
+			size_t size = 0;
+
+			rc = fsetpos(fpin, &(cur->eb_top));
+			if (rc != 0)
+				goto err;
+
+			/*
+			 * FIXME For dynamic UBI volumes we must write
+			 * the maximum available data. The
+			 * vid.data_size field is not used in this
+			 * case. The dynamic volume user is
+			 * responsible for the content.
+			 */
+			if (a->vol_split == SPLIT_DATA) {
+				/* Write only data section */
+				if (cur->vid.vol_type == UBI_VID_DYNAMIC) {
+					/* FIXME Formular is not
+					   always right ... */
+					size = a->bsize - a->hsize;
+				} else
+					size = be32_to_cpu(cur->vid.data_size);
+
+				fseek(fpin,
+				      be32_to_cpu(cur->ec.data_offset),
+				      SEEK_CUR);
+			}
+			else if (a->vol_split == SPLIT_RAW)
+				/* write entire eraseblock */
+				size = a->bsize;
+
+			snprintf(filename, MAXPATH, FN_VOLSP,
+				 a->odir_path,
+				 be32_to_cpu(cur->vid.vol_id),
+				 be32_to_cpu(cur->vid.lnum),
+				 be32_to_cpu(cur->vid.leb_ver), count);
+			rc = extract_data(fpin, size, filename);
+			if (rc < 0)
+				goto err;
+		}
+
+ invalid:
+		/* split eraseblocks */
+		if (a->eb_split) {
+			/* jump to top of block */
+			rc = fsetpos(fpin, &(cur->eb_top));
+			if (rc != 0)
+				goto err;
+
+			if (strcmp(raw_path, FN_INVAL) == 0)
+				snprintf(filename, MAXPATH, raw_path,
+					 a->odir_path, count, reason);
+			else
+				snprintf(filename, MAXPATH, raw_path,
+					 a->odir_path,
+					 count,
+					 be32_to_cpu(cur->vid.vol_id),
+					 be32_to_cpu(cur->vid.lnum),
+					 be32_to_cpu(cur->vid.leb_ver),
+					 reason);
+
+			rc = extract_data(fpin, a->bsize, filename);
+			if (rc < 0)
+				goto err;
+		}
+
+		/* append to simple linked list */
+		if (first == NULL)
+			next_ptr = &first;
+		else
+			next_ptr = &next->next;
+
+		*next_ptr = malloc(sizeof(**next_ptr));
+		if (*next_ptr == NULL) {
+			ERR_MSG("out of memory\n");
+			rc = -ENOMEM;
+			goto err;
+		}
+		memset(*next_ptr, 0, sizeof(**next_ptr));
+
+		next = *next_ptr;
+		memcpy(next, cur, sizeof(*next));
+		next->next = NULL;
+
+		count++;
+		rc = fsetpos(fpin, &(cur->eb_top));
+		if (rc != 0)
+			goto err;
+		fseek(fpin, a->bsize, SEEK_CUR);
+		memset(cur, 0, sizeof(*cur));
+
+		fgetpos(fpin, &(cur->eb_top));
+	}
+
+ out:
+	for (i = 0; i < vc; i++) {
+		rc = rebuild_volume(fpin, &vols[i], &head, a->odir_path,
+			       a->bsize, a->hsize);
+		if (rc < 0)
+			goto err;
+	}
+
+	/* if there were no volumes specified, rebuild them all,
+	 * UNLESS eb_ or vol_ split or analyze was specified */
+	if ((vc == 0) && (!a->eb_split) && (!a->vol_split) &&
+	    (!a->analyze) && (!a->itable)) {
+		rc = rebuild_volume(fpin, NULL, &head, a->odir_path, a->bsize,
+				    a->hsize);
+		if (rc < 0)
+			goto err;
+	}
+
+ err:
+	free(cur);
+
+	if (a->analyze) {
+		char fname[PATH_MAX + 1];
+		FILE *fp;
+
+		unubi_analyze(&head, first, a->odir_path);
+
+		/* prepare output files */
+		memset(fname, 0, PATH_MAX + 1);
+		snprintf(fname, PATH_MAX, "%s/%s", a->odir_path, FN_EH_STAT);
+		fp = fopen(fname, "w");
+		if (fp != NULL) {
+			eb_chain_print(fp, head);
+			fclose(fp);
+		}
+	}
+	eb_chain_destroy(&head);
+	eb_chain_destroy(&first);
+
+	return rc;
+}
+
+
+/**
+ * handles command line arguments, then calls unubi_volumes
+ **/
+int
+main(int argc, char *argv[])
+{
+	int rc, free_a_odir;
+	size_t vols_len;
+	uint32_t *vols;
+	FILE* fpin;
+	struct args a;
+
+	rc = 0;
+	free_a_odir = 0;
+	vols_len = 0;
+	vols = NULL;
+	fpin = NULL;
+	init_crc32_table(crc32_table);
+
+	/* setup struct args a */
+	memset(&a, 0, sizeof(a));
+	a.bsize = 128 * KIB;
+	a.hsize = 2 * KIB;
+	a.vols = malloc(sizeof(*a.vols) * UBI_MAX_VOLUMES);
+	if (a.vols == NULL) {
+		ERR_MSG("out of memory\n");
+		rc = ENOMEM;
+		goto err;
+	}
+	memset(a.vols, 0, sizeof(*a.vols) * UBI_MAX_VOLUMES);
+
+	/* parse args and check for validity */
+	parse_opt(argc, argv, &a);
+	if (a.img_path == NULL) {
+		ERR_MSG("no image file specified\n");
+		rc = EINVAL;
+		goto err;
+	}
+	else if (a.odir_path == NULL) {
+		char *ptr;
+		int len;
+
+		ptr = strrchr(a.img_path, '/');
+		if (ptr == NULL)
+			ptr = a.img_path;
+		else
+			ptr++;
+
+		len = strlen(DIR_FMT) + strlen(ptr);
+		free_a_odir = 1;
+		a.odir_path = malloc(sizeof(*a.odir_path) * len);
+		if (a.odir_path == NULL) {
+			ERR_MSG("out of memory\n");
+			rc = ENOMEM;
+			goto err;
+		}
+		snprintf(a.odir_path, len, DIR_FMT, ptr);
+	}
+
+	fpin = fopen(a.img_path, "rb");
+	if (fpin == NULL) {
+		ERR_MSG("couldn't open file for reading: "
+			"%s\n", a.img_path);
+		rc = EINVAL;
+		goto err;
+	}
+
+	rc = mkdir(a.odir_path, 0777);
+	if ((rc < 0) && (errno != EEXIST)) {
+		ERR_MSG("couldn't create ouput directory: "
+			"%s\n", a.odir_path);
+		rc = -rc;
+		goto err;
+	}
+
+	/* fill in vols array */
+	vols_len = count_set(a.vols, UBI_MAX_VOLUMES);
+	if (vols_len > 0) {
+		vols = malloc(sizeof(*vols) * vols_len);
+		if (vols == NULL) {
+			ERR_MSG("out of memory\n");
+			rc = ENOMEM;
+			goto err;
+		}
+		collapse(a.vols, UBI_MAX_VOLUMES, vols, vols_len);
+	}
+
+	/* unubi volumes */
+	rc = unubi_volumes(fpin, vols, vols_len, &a);
+	if (rc < 0) {
+		/* ERR_MSG("error encountered while working on image file: "
+		   "%s\n", a.img_path); */
+		rc = -rc;
+		goto err;
+	}
+
+ err:
+	free(a.vols);
+	if (free_a_odir != 0)
+		free(a.odir_path);
+	if (fpin != NULL)
+		fclose(fpin);
+	if (vols_len > 0)
+		free(vols);
+	return rc;
+}
diff --git a/ubi-utils/old-utils/src/unubi_analyze.c b/ubi-utils/old-utils/src/unubi_analyze.c
new file mode 100644
index 0000000..ceaa85f
--- /dev/null
+++ b/ubi-utils/old-utils/src/unubi_analyze.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006, 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.
+ */
+
+/*
+ * Authors: Drake Dowsett, dowsett@de.ibm.com
+ * Contact: Andreas Arnez, arnez@de.ibm.com
+ *
+ * unubi uses the following functions to generate analysis output based on
+ * the header information in a raw-UBI image
+ */
+
+/*
+ * TODO: use OOB data to check for eraseblock validity in NAND images
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <mtd_swab.h>
+
+#include "unubi_analyze.h"
+#include "crc32.h"
+
+#define EC_X_INT	50
+
+/**
+ * intcmp - function needed by qsort to order integers
+ **/
+int intcmp(const void *a, const void *b)
+{
+	int A = *(int *)a;
+	int B = *(int *)b;
+	return A - B;
+}
+
+int longcmp(const void *a, const void *b)
+{
+	long long A = *(long long *)a;
+	long long B = *(long long *)b;
+	return A - B;
+}
+
+
+/**
+ * unubi_analyze_group_index - finds the normalized index in an array
+ * item:	look for this item in the array
+ * array:	array to search through
+ * size:	length of the array
+ * array should be sorted for this algorithm to perform properly;
+ * if the item is not found returns -1, otherwise return value is the
+ * index in the array (note this contricts the array size to 2^32-1);
+ **/
+int
+norm_index(uint32_t item, uint32_t *array, size_t length)
+{
+	size_t i, index;
+
+	for (index = 0, i = 0; i < length; i++) {
+		if ((i != 0) && (array[i] != array[i - 1]))
+			index++;
+
+		if (item == array[i])
+			return index;
+	}
+
+	return -1;
+}
+
+
+/**
+ * unubi_analyze_ec_hdr - generate data table and plot script
+ * first:	head of simple linked list
+ * path:	folder to write into
+ * generates a data file containing the eraseblock index in the image
+ * and the erase counter found in its ec header;
+ * if the crc check fails, the line is commented out in the data file;
+ * also generates a simple gnuplot sript for quickly viewing one
+ * display of the data file;
+ **/
+int
+unubi_analyze_ec_hdr(struct eb_info *first, const char *path)
+{
+	char filename[PATH_MAX + 1];
+	size_t count, eraseblocks;
+	uint32_t crc, crc32_table[256];
+	uint64_t *erase_counts;
+	FILE* fpdata;
+	FILE* fpplot;
+	struct eb_info *cur;
+
+	if (first == NULL)
+		return -1;
+
+	/* crc check still needed for `first' linked list */
+	init_crc32_table(crc32_table);
+
+	/* prepare output files */
+	memset(filename, 0, PATH_MAX + 1);
+	snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_DATA);
+	fpdata = fopen(filename, "w");
+	if (fpdata == NULL)
+		return -1;
+
+	memset(filename, 0, PATH_MAX + 1);
+	snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_PLOT);
+	fpplot = fopen(filename, "w");
+	if (fpplot == NULL) {
+		fclose(fpdata);
+		return -1;
+	}
+
+	/* make executable */
+	chmod(filename, 0755);
+
+	/* first run: count elements */
+	count = 0;
+	cur = first;
+	while (cur != NULL) {
+		cur = cur->next;
+		count++;
+	}
+	eraseblocks = count;
+
+	erase_counts = malloc(eraseblocks * sizeof(*erase_counts));
+	if (!erase_counts) {
+		perror("out of memory");
+		exit(EXIT_FAILURE);
+	}
+
+	memset(erase_counts, 0, eraseblocks * sizeof(*erase_counts));
+
+	/* second run: populate array to sort */
+	count = 0;
+	cur = first;
+	while (cur != NULL) {
+		erase_counts[count] = be64_to_cpu(cur->ec.ec);
+		cur = cur->next;
+		count++;
+	}
+	qsort(erase_counts, eraseblocks, sizeof(*erase_counts),
+	      (void *)longcmp);
+
+	/* third run: generate data file */
+	count = 0;
+	cur = first;
+	fprintf(fpdata, "# eraseblock_no actual_erase_count "
+			"sorted_erase_count\n");
+	while (cur != NULL) {
+		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &cur->ec,
+				UBI_EC_HDR_SIZE_CRC);
+
+		if ((be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) ||
+		    (crc != be32_to_cpu(cur->ec.hdr_crc)))
+			fprintf(fpdata, "# ");
+
+		fprintf(fpdata, "%zu %llu %llu", count,
+			(unsigned long long)be64_to_cpu(cur->ec.ec),
+			(unsigned long long)erase_counts[count]);
+
+		if (be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC)
+			fprintf(fpdata, " ## bad magic: %08x",
+				be32_to_cpu(cur->ec.magic));
+
+		if (crc != be32_to_cpu(cur->ec.hdr_crc))
+			fprintf(fpdata, " ## CRC mismatch: given=%08x, "
+				"calc=%08x", be32_to_cpu(cur->ec.hdr_crc),
+				crc);
+
+		fprintf(fpdata, "\n");
+
+		cur = cur->next;
+		count++;
+	}
+	fclose(fpdata);
+
+	fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n");
+	fprintf(fpplot, "set xlabel \"eraseblock\"\n");
+
+	/* fourth run: generate plot file xtics */
+	count = 0;
+	cur = first;
+	fprintf(fpplot, "set xtics (");
+	while (cur != NULL) {
+		if ((count % EC_X_INT) == 0) {
+			if (count > 0)
+				fprintf(fpplot, ", ");
+			fprintf(fpplot, "%zd", count);
+		}
+
+		cur = cur->next;
+		count++;
+	}
+	fprintf(fpplot, ")\n");
+
+	fprintf(fpplot, "set ylabel \"erase count\"\n");
+	fprintf(fpplot, "set xrange [-1:%zu]\n", eraseblocks + 1);
+	fprintf(fpplot, "# set yrange [-1:%llu]\n",
+		(unsigned long long)erase_counts[eraseblocks - 1] + 1);
+	fprintf(fpplot, "plot \"%s\" u 1:2 t \"unsorted: %s\" with boxes\n",
+		FN_EH_DATA, FN_EH_DATA);
+	fprintf(fpplot, "# replot \"%s\" u 1:3 t \"sorted: %s\" with lines\n",
+		FN_EH_DATA, FN_EH_DATA);
+	fprintf(fpplot, "pause -1 \"press ENTER\"\n");
+
+	fclose(fpplot);
+
+	return 0;
+}
+
+
+/**
+ * unubi_analyze_vid_hdr - generate data table and plot script
+ * head:	head of complex linked list (eb_chain)
+ * path:	folder to write into
+ * generates a data file containing the volume id, logical number, leb version,
+ * and data size from the vid header;
+ * all eraseblocks listed in the eb_chain are valid (checked in unubi);
+ * also generates a simple gnuplot sript for quickly viewing one
+ * display of the data file;
+ **/
+int
+unubi_analyze_vid_hdr(struct eb_info **head, const char *path)
+{
+	char filename[PATH_MAX + 1];
+	int rc, y1, y2;
+	size_t count, step, breadth;
+	uint32_t *leb_versions, *data_sizes;
+	FILE* fpdata;
+	FILE* fpplot;
+	struct eb_info *cur;
+
+	if (head == NULL || *head == NULL)
+		return -1;
+
+	rc = 0;
+	fpdata = NULL;
+	fpplot = NULL;
+	data_sizes = NULL;
+	leb_versions = NULL;
+
+	/* prepare output files */
+	memset(filename, 0, PATH_MAX + 1);
+	snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_DATA);
+	fpdata = fopen(filename, "w");
+	if (fpdata == NULL) {
+		rc = -1;
+		goto exit;
+	}
+
+	memset(filename, 0, PATH_MAX + 1);
+	snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_PLOT);
+	fpplot = fopen(filename, "w");
+	if (fpplot == NULL) {
+		rc = -1;
+		goto exit;
+	}
+
+	/* make executable */
+	chmod(filename, 0755);
+
+	/* first run: count elements */
+	count = 0;
+	cur = *head;
+	while (cur != NULL) {
+		cur = cur->next;
+		count++;
+	}
+	breadth = count;
+
+	leb_versions = malloc(breadth * sizeof(uint32_t));
+	if (leb_versions == NULL) {
+		rc = -1;
+		goto exit;
+	}
+	memset(leb_versions, 0, breadth * sizeof(uint32_t));
+
+	data_sizes = malloc(breadth * sizeof(uint32_t));
+	if (data_sizes == NULL) {
+		rc = -1;
+		goto exit;
+	}
+	memset(data_sizes, 0, breadth * sizeof(*data_sizes));
+
+	/* second run: populate arrays to sort */
+	count = 0;
+	cur = *head;
+	while (cur != NULL) {
+		leb_versions[count] = be32_to_cpu(cur->vid.leb_ver);
+		data_sizes[count] = be32_to_cpu(cur->vid.data_size);
+		cur = cur->next;
+		count++;
+	}
+	qsort(leb_versions, breadth, sizeof(*leb_versions), (void *)intcmp);
+	qsort(data_sizes, breadth, sizeof(*data_sizes), (void *)intcmp);
+
+	/* third run: generate data file */
+	count = 0;
+	cur = *head;
+	fprintf(fpdata, "# x_axis vol_id lnum   y1_axis leb_ver   "
+		"y2_axis data_size\n");
+	while (cur != NULL) {
+		y1 = norm_index(be32_to_cpu(cur->vid.leb_ver), leb_versions,
+				breadth);
+		y2 = norm_index(be32_to_cpu(cur->vid.data_size), data_sizes,
+				breadth);
+
+		if ((y1 == -1) || (y2 == -1)) {
+			rc = -1;
+			goto exit;
+		}
+
+		fprintf(fpdata, "%zu %u %u   %u %u   %u %u\n",
+			count,
+			be32_to_cpu(cur->vid.vol_id),
+			be32_to_cpu(cur->vid.lnum),
+			y1,
+			be32_to_cpu(cur->vid.leb_ver),
+			y2,
+			be32_to_cpu(cur->vid.data_size));
+		cur = cur->next;
+		count++;
+	}
+
+	fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n");
+	fprintf(fpplot, "set xlabel \"volume\"\n");
+
+	/* fourth run: generate plot file xtics */
+	count = 0;
+	step = 0;
+	cur = *head;
+	fprintf(fpplot, "set xtics (");
+	while (cur != NULL) {
+		if (count > 0)
+			fprintf(fpplot, ", ");
+		if (step != be32_to_cpu(cur->vid.vol_id)) {
+			step = be32_to_cpu(cur->vid.vol_id);
+			fprintf(fpplot, "\"%zd\" %zd 0", step, count);
+		}
+		else
+			fprintf(fpplot, "\"%d\" %zd 1",
+				be32_to_cpu(cur->vid.lnum), count);
+		cur = cur->next;
+		count++;
+	}
+	fprintf(fpplot, ")\n");
+	fprintf(fpplot, "set nox2tics\n");
+
+	/* fifth run: generate plot file ytics */
+	count = 0;
+	cur = *head;
+	fprintf(fpplot, "set ylabel \"leb version\"\n");
+	fprintf(fpplot, "set ytics (");
+	while (cur->next != NULL) {
+		y1 = norm_index(be32_to_cpu(cur->vid.leb_ver), leb_versions,
+				breadth);
+
+		if (y1 == -1) {
+			rc = -1;
+			goto exit;
+		}
+
+		if (count > 0)
+			fprintf(fpplot, ", ");
+
+		fprintf(fpplot, "\"%u\" %u", be32_to_cpu(cur->vid.leb_ver),
+			y1);
+
+		cur = cur->next;
+		count++;
+	}
+	fprintf(fpplot, ")\n");
+
+	/* sixth run: generate plot file y2tics */
+	count = 0;
+	cur = *head;
+	fprintf(fpplot, "set y2label \"data size\"\n");
+	fprintf(fpplot, "set y2tics (");
+	while (cur != NULL) {
+		y2 = norm_index(be32_to_cpu(cur->vid.data_size),
+				data_sizes, breadth);
+
+		if (y2 == -1) {
+			rc = -1;
+			goto exit;
+		}
+
+		if (count > 0)
+			fprintf(fpplot, ", ");
+
+		fprintf(fpplot, "\"%u\" %u", be32_to_cpu(cur->vid.data_size),
+			y2);
+
+		cur = cur->next;
+		count++;
+	}
+	fprintf(fpplot, ")\n");
+
+	y1 = norm_index(leb_versions[breadth - 1], leb_versions, breadth);
+	y2 = norm_index(data_sizes[breadth - 1], data_sizes, breadth);
+	fprintf(fpplot, "set xrange [-1:%zu]\n", count + 1);
+	fprintf(fpplot, "set yrange [-1:%u]\n", y1 + 1);
+	fprintf(fpplot, "set y2range [-1:%u]\n", y2 + 1);
+	fprintf(fpplot, "plot \"%s\" u 1:4 t \"leb version: %s\" "
+			"axes x1y1 with lp\n", FN_VH_DATA, FN_VH_DATA);
+	fprintf(fpplot, "replot \"%s\" u 1:6 t \"data size: %s\" "
+			"axes x1y2 with lp\n", FN_VH_DATA, FN_VH_DATA);
+	fprintf(fpplot, "pause -1 \"press ENTER\"\n");
+
+ exit:
+	if (fpdata != NULL)
+		fclose(fpdata);
+	if (fpplot != NULL)
+		fclose(fpplot);
+	if (data_sizes != NULL)
+		free(data_sizes);
+	if (leb_versions != NULL)
+		free(leb_versions);
+
+	return rc;
+}
+
+
+/**
+ * unubi_analyze - run all analyses
+ * head:	eb_chain head
+ * first:	simple linked list of eraseblock headers (use .next)
+ * path:	directory (without trailing slash) to output to
+ * returns 0 upon successful completion, or -1 otherwise
+ **/
+int
+unubi_analyze(struct eb_info **head, struct eb_info *first, const char *path)
+{
+	int ec_rc, vid_rc;
+
+	if (path == NULL)
+		return -1;
+
+	ec_rc = unubi_analyze_ec_hdr(first, path);
+	vid_rc = unubi_analyze_vid_hdr(head, path);
+	if (ec_rc < 0 || vid_rc < 0)
+		return -1;
+
+	return 0;
+}
diff --git a/ubi-utils/old-utils/src/unubi_analyze.h b/ubi-utils/old-utils/src/unubi_analyze.h
new file mode 100644
index 0000000..c478f53
--- /dev/null
+++ b/ubi-utils/old-utils/src/unubi_analyze.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006, 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 __UNUBI_ANALYZE_H__
+#define __UNUBI_ANALYZE_H__
+
+/*
+ * Author:  Drake Dowsett
+ * Contact: Andreas Arnez (arnez@de.ibm.com)
+ *
+ * Eraseblock Chain
+ *
+ * A linked list structure to order eraseblocks by volume and logical number
+ * and to update by version number. Doesn't contain actual eraseblock data
+ * but rather the erasecounter and volume id headers as well as a position
+ * indicator.
+ *
+ * Diagram Example:
+ *
+ * [V1.0v0]->[V1.1v2]->[V1.2v1]->[V2.0v2]->[V2.1v0]->[V2.2v1]->NULL
+ *     |         |         |         |         |         |
+ *   NULL    [V1.1v1]  [V1.2v0]  [V2.0v1]    NULL    [V2.2v0]
+ *               |         |         |                   |
+ *           [V1.1v0]    NULL    [V2.0v0]              NULL
+ *               |                   |
+ *             NULL                NULL
+ *
+ * [VA.BvC] represents the eb_info for the eraseblock with the vol_id A,
+ * lnum B and leb_ver C
+ * -> represents the `next' pointer
+ * | represents the `older' pointer
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <mtd/ubi-media.h>
+
+#define FN_EH_STAT      "analysis_blocks.txt"
+#define FN_EH_DATA	"analysis_ec_hdr.data"
+#define FN_EH_PLOT	"analysis_ec_hdr.plot"
+#define FN_VH_DATA	"analysis_vid_hdr.data"
+#define FN_VH_PLOT	"analysis_vid_hdr.plot"
+
+struct eb_info {
+	struct ubi_ec_hdr ec;
+	struct ubi_vid_hdr vid;
+
+	fpos_t eb_top;
+	uint32_t linear;
+	int ec_crc_ok;
+	int vid_crc_ok;
+	int data_crc_ok;
+	uint32_t phys_addr;
+	int phys_block;
+
+	struct eb_info *next;
+	struct eb_info *older;
+};
+
+int eb_chain_insert(struct eb_info **head, struct eb_info *item);
+
+int eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum,
+		      struct eb_info **pos);
+
+int eb_chain_print(FILE *stream, struct eb_info *head);
+
+int eb_chain_destroy(struct eb_info **head);
+
+int unubi_analyze(struct eb_info **head, struct eb_info *first,
+		  const char *path);
+
+#endif /* __UNUBI_ANALYZE_H__ */
diff --git a/ubi-utils/old-utils/testcases.txt b/ubi-utils/old-utils/testcases.txt
new file mode 100644
index 0000000..dcc1c35
--- /dev/null
+++ b/ubi-utils/old-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/perl/f128_nand_sample.cfg b/ubi-utils/perl/f128_nand_sample.cfg
deleted file mode 100644
index e468d9d..0000000
--- a/ubi-utils/perl/f128_nand_sample.cfg
+++ /dev/null
@@ -1,38 +0,0 @@
-[targets]
-complete=ipl,spl,bootenv,kernel,rootfs
-bootcode=spl,bootenv
-
-# Build sections
-[ipl] 
-image=ipl.bin
-raw_starts=0x00000000
-raw_total_size=128kiB 
-
-[spl]
-image=u-boot.bin
-ubi_ids=2,3
-ubi_size=2MiB
-ubi_type=static
-ubi_names=spl_0,spl_1
-
-[bootenv]
-bootenv_file=bootenv_complete.txt
-ubi_ids=4,5
-ubi_size=128kiB
-ubi_type=static
-ubi_names=bootenv_0,bootenv_1
-
-[kernel]
-image=vmlinux.bin
-ubi_ids=6,7
-ubi_size=6MiB
-ubi_type=static
-ubi_names=kernel_0,kernel_1
-
-[rootfs]
-image=rootfs.bin
-ubi_ids=8,9
-ubi_alignment=2kiB
-ubi_size=16MiB 
-ubi_type=dynamic
-ubi_names=rootfs_0,rootfs_1
diff --git a/ubi-utils/perl/f64_nor_sample.cfg b/ubi-utils/perl/f64_nor_sample.cfg
deleted file mode 100644
index fd44e27..0000000
--- a/ubi-utils/perl/f64_nor_sample.cfg
+++ /dev/null
@@ -1,39 +0,0 @@
-[targets]
-complete=ipl,spl,bootenv,kernel,rootfs
-bootcode=spl,bootenv
-rootfs=rootfs
-
-# Build sections
-[ipl] 
-image=ipl.bin
-raw_starts=0x02FE0000, 0x03FE0000
-raw_total_size=128kiB 
-
-[spl]
-image=u-boot.bin
-ubi_ids=2,3
-ubi_size=2MiB
-ubi_type=static
-ubi_names=spl_0,spl_1
-
-[bootenv]
-bootenv_file=bootenv_complete.txt
-ubi_ids=4,5
-ubi_size=128kiB
-ubi_type=static
-ubi_names=bootenv_0,bootenv_1
-
-[kernel]
-image=vmlinux.bin
-ubi_ids=6,7
-ubi_size=6MiB
-ubi_type=static
-ubi_names=kernel_0,kernel_1
-
-[rootfs]
-image=rootfs.bin
-ubi_ids=8,9
-ubi_alignment=2kiB
-ubi_size=16128kiB 
-ubi_type=dynamic
-ubi_names=rootfs_0,rootfs_1
diff --git a/ubi-utils/perl/mkpfi b/ubi-utils/perl/mkpfi
deleted file mode 100755
index 2cce587..0000000
--- a/ubi-utils/perl/mkpfi
+++ /dev/null
@@ -1,723 +0,0 @@
-#!/usr/bin/perl
-#
-# 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.
-#
-
-#
-# mkpfi
-#
-# This perl program is assembles PFI files from a config file.
-#
-# Author: Oliver Lohmann (oliloh@de.ibm.com)
-#
-use warnings;
-use strict;
-use lib "/usr/lib/perl5"; # Please change this path as you need it, or
-			  # make a proposal how this could be done
-			  # nicer.
-use Getopt::Long;
-use Pod::Usage;
-use Config::IniFiles;
-use File::Temp;
-
-# ----------------------------------------------------------------------------
-# Versions
-our $version : unique = "0.1";
-our $pfi_version : unique = "0x1";
-
-# ----------------------------------------------------------------------------
-# Globals
-my $verbose = 0;
-my $cfg;
-
-my %opts = ();
-my %files = (config => "");
-my @tmp_files;
-
-my %tools = (ubicrc32 => "ubicrc32");
-
-# ----------------------------------------------------------------------------
-# Processing the input sections
-#
-# The idea is to combine each section entry with a function
-# in order to allow some kind of preprocessing for the values
-# before they are written into the PFI file.
-# This is especially useful to be more verbose and
-# user-friendly in the layout file.
-#
-# All key-function hashes are applied after the general
-# validation of the configuration file.
-# If any mandatory key is missing in a section the user
-# will be informed and the PFI creation process is aborted.
-#
-# Default keys will be checked for their presence inside the config
-# file. If they are missing, they will be generated with appr. values.
-
-# Mandatory keys for UBI volumes.
-my %ubi_keys = ("ubi_ids"       => \&check_id_list,
-		"ubi_size"      => \&replace_num,
-		"ubi_type"      => \&replace_type,
-		"ubi_names"     => \&remove_spaces,
-		"ubi_alignment" => \&replace_num);
-
-# Mandatory keys for RAW sections.
-my %raw_keys = ("raw_starts"     => \&expand_starts,
-		"raw_total_size" => \&replace_num);
-
-# Common default keys for documentation and control purposes.
-my %common_keys = ("flags" => \&replace_num,
-		   "label" => \&do_nothing);
-
-# Define any defaults here. Values which maintained in this default
-# region need not to be specified by the user explicitly.
-my %def_ubi_keys      = ("ubi_alignment" => [\&set_default, "0x1"]);
-my %def_raw_keys      = ();
-my %def_common_keys   = ("flags"	 => [\&set_default, "0x0"],
-			 "label"	 => [\&generate_label, ""]);
-
-# ----------------------------------------------------------------------------
-# Input keys, actually the path to the input data.
-
-my %input_keys = ("image" => \&do_nothing);
-
-# Placeholder keys allow the replacement via a special
-# purpose function. E.g. the bootenv_file key will be used
-# to generate bootenv binary data from an text file and
-# replace the bootenv_file key with an image key to handle it
-# in the same way in the further creation process.
-my %input_placeholder_keys = ("bootenv_file" => \&create_bootenv_image);
-
-# ----------------------------------------------------------------------------
-# Helper
-
-# @brief Get current time string.
-sub get_date {
-	my $tmp = scalar localtime;
-	$tmp =~ s/ /_/g;
-	return $tmp;
-}
-
-# @brief Print an info message to stdout.
-sub INFO($) {
-	my $str = shift;
-
-	if (!$verbose) {
-		return;
-	}
-
-	print STDOUT $str;
-}
-
-# @brief Print an error message to stderr.
-sub ERR($) {
-	my $str = shift;
-	print STDERR $str;
-}
-
-# @brief Print a warning message to stderr.
-sub WARN($) {
-	my $str = shift;
-	print STDERR $str;
-}
-
-sub parse_command_line($) {
-	my $opt = shift;
-	my $result = GetOptions( "help"	     => \$$opt{'help'},
-				 "man"	     => \$$opt{'man'},
-				 "config=s"  => \$$opt{'config'},
-				 "verbose"   => \$$opt{'verbose'},
-			       ) or pod2usage(2);
-	pod2usage(1) if defined ($$opt{help});
-	pod2usage(-verbose => 2) if defined ($$opt{man});
-
-	$verbose = $$opt{verbose} if defined $$opt{verbose};
-
-	if (!defined $$opt{config}) {
-		ERR("[ ERROR: No config file specified. Aborting...\n");
-		exit 1;
-	}
-
-}
-
-# @brief Check if all needed tools are in PATH.
-sub check_tools {
-	my $err = 0;
-	my $key;
-
-	foreach $key (keys %tools) {
-		if (`which $tools{$key}` eq "") {
-			ERR("\n") if ($err == 0);
-			ERR("! Please add the tool \'$tools{$key}\' " .
-				"to your path!\n");
-			$err = 1;
-		}
-	}
-	die "[ ERROR: Did not find all needed tools!\n" if $err;
-}
-
-sub open_cfg_file($) {
-	my $fname = shift;
-	my $res = new Config::IniFiles( -file => $fname );
-
-	die "[ ERROR: Cannot load your config file!\n" if (!defined $res);
-	return $res;
-}
-
-sub set_default($$$$) {
-	my ($cfg, $section, $parameter, $def_value) = @_;
-	$cfg->newval($section, $parameter, $def_value);
-	return;
-}
-
-sub generate_label($$$$) {
-	my ($cfg, $section, $parameter, $def_value) = @_;
-	my $new_label = $def_value . $section;
-	$new_label .= "_" . get_date;
-	$cfg->newval($section, $parameter, $new_label);
-	return;
-}
-
-# @brief   Converts any num to a unified hex string, i.e the resulting value
-#	   always starts with "0x" and is aligned to 8 hexdigits.
-# @return  Returns 0 on success, otherwise an error occured.
-#
-sub any_num_to_hex($$) {
-	my $val = shift;
-	my $res = shift;
-
-	# M(iB)
-	if ($val =~ m/([0-9]+)[Mm][i]?[Bb]?/g) {
-		$$res = sprintf("0x%08x", $1 * 1024 * 1024);
-	}
-	# k(iB)
-	elsif ($val =~ m/([0-9]+)[kK][i]?[Bb]?/g) {
-		$$res = sprintf("0x%08x", $1 * 1024);
-	}
-	# hex
-	elsif ($val =~ m/0x?([0-9a-fA-F]+)/g) {
-		$$res = sprintf("0x%08x", hex $1);
-	}
-	# decimal
-	elsif ($val =~ m/^([0-9]+)$/g) {
-		$$res = sprintf("0x%08x", $1);
-	}
-	else {
-		$$res = "";
-		return -1;
-	}
-
-	return 0;
-}
-
-sub remove_spaces($$$) {
-	my ($cfg, $section, $parameter) = @_;
-	my ($start, @starts, @new_starts);
-	my $val = $cfg->val($section, $parameter);
-	my $res;
-
-	$val =~ s/ //g; # spaces
-	$cfg->newval($section, $parameter, $val);
-}
-
-sub expand_starts($$$) {
-	my ($cfg, $section, $parameter) = @_;
-	my ($start, @starts, @new_starts);
-	my $val = $cfg->val($section, $parameter);
-	my $res;
-
-	$val =~ s/ //g; # spaces
-	@starts = split(/,/, $val);
-
-	foreach $start (@starts) {
-		if (any_num_to_hex($start, \$res) != 0) {
-			ERR("[ ERROR: [$section]\n");
-			ERR("[        Expecting a list of numeric " .
-			    "values for parameter: $parameter\n");
-			exit 1;
-		}
-		push (@new_starts, $res);
-	}
-	$res = join(',', @starts);
-
-	$cfg->newval($section, $parameter, $res);
-}
-
-sub check_id_list($$$) {
-	my ($cfg, $section, $parameter) = @_;
-	my $val = $cfg->val($section, $parameter);
-	my $res;
-
-	if (!($val =~ m/^[0-9]+[,0-9]*/)) {
-		ERR("[ ERROR: Syntax error in 'ubi_ids' in " .
-		    "section '$section': $val\n");
-			ERR("[ Aborting... ");
-			exit 1;
-	}
-}
-
-sub replace_type($$$) {
-	my ($cfg, $section, $parameter) = @_;
-	my $val = $cfg->val($section, $parameter);
-	my $res;
-
-	$res = lc($val);
-	grep {$res eq $_} ('static', 'dynamic')
-	    or die "[ ERROR: Unknown UBI Volume Type in " .
-	    "section '$section': $val\n";
-
-	$cfg->newval($section, $parameter, $res);
-}
-
-
-sub replace_num($$$) {
-	my ($cfg, $section, $parameter) = @_;
-	my $val = $cfg->val($section, $parameter);
-	my $res = "";
-
-	if (any_num_to_hex($val, \$res) != 0) {
-		ERR("[ ERROR: [$section]\n");
-		ERR("[        Expecting a numeric value " .
-		    "for parameter: $parameter\n");
-		exit 1;
-	}
-	$cfg->newval($section, $parameter, $res);
-}
-
-sub do_nothing($$$) {
-	my ($cfg, $section, $parameter) = @_;
-	return;
-}
-
-sub bootenv_sanity_check($) {
-	my $env = shift;	# hash array containing bootenv
-	my %pdd = ();
-
-	defined($$env{'pdd'}) or return "'pdd' not defined";
-	foreach (split /,/, $$env{'pdd'}) {
-		defined($$env{$_}) or return "undefined '$_' in pdd";
-		$pdd{$_} = 1;
-	}
-
-	defined $$env{'pdd_preserve'} or
-		return "";
-	foreach (split /,/, $$env{'pdd_preserve'}) {
-		defined($pdd{$_})
-			or return "pdd_preserve field '$_' not in pdd";
-	}
-	return "";
-}
-
-sub create_bootenv_image($$$) {
-	my ($cfg, $section, $parameter) = @_;
-	my $txt_fn = $cfg->val($section, "bootenv_file");
-	my $in;
-
-	my %value = ();
-	my @key = ();
-
-	open $in, "<", $txt_fn
-		or die "[ ERROR: can't open bootenv file '$txt_fn'.\n";
-	while (<$in>) {
-		next if (/^\s*(\#.*)?$/); # Skip comments/whitespace.
-
-		if (/^(\S+?)\+\=(.*)$/) {
-			defined($value{$1}) or
-				die "$txt_fn:$.: error: appending to" .
-					" non-existent '$1'\n";
-			$value{$1} .= $2;
-		} elsif (/^(\S+?)\=(.*)$/) {
-			not defined($value{$1}) or
-				die "$txt_fn:$.: error: trying to" .
-					" redefine '$1'\n";
-			push @key, $1;
-			$value{$1} = $2;
-		} else {
-			die "$txt_fn:$.: error: unrecognized syntax\n";
-		}
-	}
-	close $in;
-
-	$_ = &bootenv_sanity_check(\%value)
-		and die "$txt_fn: error: $_\n";
-
-	my $tmp_file = new File::Temp();
-	push (@tmp_files, $tmp_file);
-
-	foreach (@key) {
-		print $tmp_file "$_=", $value{$_}, "\0";
-	}
-	close $tmp_file;
-
-	$cfg->newval($section, "image", $tmp_file-> filename);
-}
-
-sub process_keys($$$) {
-	my ($cfg, $section, $keys) = @_;
-	my @parameters = $cfg->Parameters($section);
-	my $i;
-
-	for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) {
-		if (defined($$keys{$parameters[$i]})) {
-			$$keys{$parameters[$i]}->($cfg, $section,
-					$parameters[$i]);
-		}
-	}
-
-}
-
-sub is_in_keylist($$) {
-	my ($key, $keys) = @_;
-	my $i;
-
-	for ($i = 0; $i < scalar(@$keys); $i++) {
-		if ($$keys[$i] eq $key) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-sub check_default_keys($$$) {
-	my ($cfg, $section, $keys) = @_;
-	my @parameters = $cfg->Parameters($section);
-	my $key;
-
-	foreach $key (keys %$keys) {
-		if (!is_in_keylist($key, \@parameters)) {
-			$$keys{$key}[0]->
-				($cfg, $section, $key, $$keys{$key}[1]);
-		}
-	}
-
-}
-
-
-
-sub check_keys($$$) {
-	my ($cfg, $section, $keys) = @_;
-	my @parameters = $cfg->Parameters($section);
-	my ($i, $key, $err);
-
-	$err = 0;
-	for ($i = 0 ; $i < scalar(@$keys) ; $i++ ) {
-		if (!is_in_keylist($$keys[$i], \@parameters)) {
-			ERR("[ ERROR: [$section]\n") if $err == 0;
-			$err = 1;
-			ERR("[        Missing key '$$keys[$i]'\n");
-		}
-	}
-
-	if ($err) {
-		ERR("[ Aborting...\n");
-		exit 1;
-	}
-}
-
-sub push_pfi_data($$$$$) {
-	my ($cfg, $section, $pfi_infos, $keys, $mode) = @_;
-	my ($tmp, $i, $hdr);
-
-	my %pfi_info = ();
-	$pfi_info{'mode'} = $mode;
-	$pfi_info{'image'} = $cfg->val($section, "image");
-
-	# Build the PFI header
-	$hdr  = sprintf("PFI!\n");
-	$hdr .= sprintf("version=0x%08x\n", hex $pfi_version);
-	$hdr .= sprintf("mode=$mode\n");
-
-	# calculate the size of the binary data part
-	$tmp = -s $cfg->val($section, "image");
-	if (!defined $tmp) {
-		ERR("[ ERROR: [$section]\n");
-		ERR("[        Missing input image: "
-				. $cfg->val($section, "image") . "\n");
-		exit 1;
-	}
-	# Check for the image to fit into the given space
-	my $quota;
-	if ($mode eq 'raw') {
-		$quota = oct $cfg->val($section, "raw_total_size");
-	} elsif ($mode eq 'ubi') {
-		$quota = oct $cfg->val($section, "ubi_size");
-	}
-	$tmp <= $quota
-		or die "[ERROR: image file too big: " .
-		$cfg->val($section, "image") . "\n";
-	$pfi_info{'size'} = $tmp;
-
-	$hdr .= sprintf("size=0x%08x\n", $tmp);
-
-	my $img_file = $cfg->val($section, "image");
-	my $crc32 = `$tools{'ubicrc32'} $img_file 2>&1`;
-	if (any_num_to_hex($crc32, \$tmp) != 0) {
-		die "[ ERROR: $tools{'ubicrc32'} returned with errors";
-	}
-	$hdr .= sprintf("crc=$tmp\n");
-
-
-	# Process all remaining keys
-	for ($i = 0; $i < scalar (@$keys); $i++) {
-		if ($$keys[$i] eq "image") { # special case image input file
-			if (! -e ($tmp = $cfg->val($section, "image"))) {
-				ERR("[ ERROR: [$section]\n");
-				ERR("[        Cannot find input file $tmp\n");
-				exit 1;
-			}
-			next;
-		}
-		$hdr .= sprintf("%s=%s\n", $$keys[$i],
-				$cfg->val($section, $$keys[$i]));
-	}
-
-	$hdr .= sprintf("\n"); # end marker for PFI-header
-
-	$pfi_info{'header'} = $hdr;
-
-	# store in the header list
-	push @$pfi_infos, \%pfi_info;
-}
-
-sub process_section($$$$$$) {
-	my ($cfg, $section, $pfi_infos, $custom_keys,
-			$def_custom_keys, $mode) = @_;
-	my @keys = (keys %common_keys, keys %$custom_keys);
-	my @complete_keys = (@keys, keys %input_keys);
-
-	# set defaults if necessary
-	check_default_keys($cfg, $section, $def_custom_keys);
-	check_default_keys($cfg, $section, \%def_common_keys);
-
-	# check for placeholders...
-	process_keys($cfg, $section, \%input_placeholder_keys);
-
-	# VALIDATE layout.cfg entries
-	check_keys($cfg, $section, \@complete_keys);
-
-	# execute linked functions (if any)
-	process_keys($cfg, $section, \%common_keys);
-	process_keys($cfg, $section, $custom_keys);
-
-	push_pfi_data($cfg, $section, $pfi_infos, \@keys, $mode);
-}
-
-sub get_section_info($$) {
-	my ($cfg, $section) = @_;
-	my @parameters = $cfg->Parameters($section);
-	my ($ubi, $raw, $i, @res);
-
-	$ubi = $raw = 0;
-	for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) {
-		if ($parameters[$i] =~ m/ubi_/gi) {
-			$ubi = 1;
-			@res = (\%ubi_keys, \%def_ubi_keys, "ubi");
-		}
-		if ($parameters[$i] =~ m/raw_/gi) {
-			$raw = 1;
-			@res = (\%raw_keys, \%def_raw_keys, "raw");
-		}
-	}
-
-	if (($ubi + $raw) != 1)	{ # double definition in section
-		ERR("[ ERROR: Layout error in section '$section'\n");
-		exit 1;
-	}
-
-	return @res;
-}
-
-sub mk_target_list($$) {
-	my $val = shift;
-	my $tmp = shift;
-	my $complete = 0;
-
-	if ($val =~ m/\((.*)\)/g) {
-		$val = $1;
-		$complete = 1;
-	}
-	$val =~ s/ //g; # spaces
-
-	@$tmp = split(/,/, $val);
-
-	return $complete;
-}
-
-sub copy_bytes($$$) {
-	my ($in, $out, $to_copy) = @_;
-
-	while ($to_copy) {
-		my $buf;
-		my $bufsize = 1024*1024;
-
-		$bufsize < $to_copy or $bufsize = $to_copy;
-		read($in, $buf, $bufsize) == $bufsize
-			or die "[ ERROR: Image file shrunk during operation\n";
-		print $out $buf;
-		$to_copy -= $bufsize;
-	}
-}
-
-sub write_target($$) {
-	my ($pfi_infos, $target) = @_;
-	my ($pfi_info);
-
-	INFO("[ Writting target pfi file: '$target.pfi'...\n");
-	if (-e "$target.pfi") {
-		WARN("! Replaced old pfi...\n");
-		`rm -f $target.pfi`;
-	}
-	open(FILE, ">", "$target.pfi")
-		or die "[ ERROR: Cannot create output file: $target.pfi\n";
-	binmode(FILE);
-
-	# @FIXME sort by mode (first raw, then ubi)
-	# Currently this ordering is based on a string comparism. :-)
-	@$pfi_infos = sort {(lc $$a{'mode'}) cmp (lc $$b{'mode'})} @$pfi_infos;
-
-	# Print all headers first
-	foreach $pfi_info (@$pfi_infos) {
-		print FILE $$pfi_info{'header'};
-
-	}
-	# Print the linked data sections
-	print FILE "DATA\n";
-	foreach $pfi_info (@$pfi_infos) {
-		open(IMAGE, "<", $$pfi_info{'image'})
-				or die "[ ERROR: Cannot open input image: " .
-				"$$pfi_info{'image'}" . "\n";
-		binmode(IMAGE);
-		&copy_bytes(\*IMAGE, \*FILE, $$pfi_info{'size'});
-		close(IMAGE) or die "[ ERROR: Cannot close input image: " .
-				"$$pfi_info{'image'}" . "\n";
-	}
-	close(FILE) or die "[ ERROR: Cannot close output file: $target.pfi\n";
-}
-
-sub process_config($) {
-	my $cfg = shift;
-	my @sections = $cfg->Sections;
-	my ($i, $j, $keylist, $def_keylist, $mode, $tmp,
-			@tlist, $complete,@pfi_infos);
-
-	my @parameters = $cfg->Parameters("targets") or
-		die "[ ERROR: Config file has no 'targets' section!\n";
-
-	for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) {
-		INFO("[ Processing target '$parameters[$i]'...\n");
-		@pfi_infos = ();
-
-		# get a list of subtargets
-		$complete = mk_target_list($cfg->val("targets",
-					$parameters[$i]), \@tlist);
-		# build all subtargets
-		for ($j = 0 ; $j < scalar(@tlist) ; $j++ ) {
-			($keylist, $def_keylist, $mode)
-				= get_section_info($cfg, $tlist[$j]);
-			process_section($cfg, $tlist[$j],
-					\@pfi_infos,
-					$keylist, $def_keylist, $mode);
-		}
-
-		write_target(\@pfi_infos, $parameters[$i]);
-	}
-
-	INFO("[ Success.\n");
-
-
-}
-
-sub clear_files() {
-	# @FIXME:
-	# Works implicitly and Fedora seems to have removed
-	# the cleanup call. Thus for now, inactive.
-	# File::Temp::cleanup();
-}
-
-require 5.008_000;		# Tested with version 5.8.0.
-select STDOUT; $| = 1;		# make STDOUT output unbuffered
-select STDERR; $| = 1;		# make STDERR output unbuffered
-
-parse_command_line(\%opts);
-check_tools;
-$cfg = open_cfg_file($opts{config});
-process_config($cfg);
-clear_files;
-
-__END__
-
-
-=head1 NAME
-
-mkpfi - Using GetOpt::Long, Pod::Usage, Config::IniFiles
-
-
-=head1 SYNOPSIS
-
-mkpfi  [OPTIONS ...]
-
-
-	OPTION
-
-	[--config] [--help] [--man]
-
-
-=head1 ABSTRACT
-
-Perl script for generating pdd pfi files from given config files.
-
-=head1 OPTIONS
-
-=over
-
-=item B<--help>
-
-Print out brief help message.
-
-=item B<--usage>
-
-Print usage.
-
-=item B<--config>
-
-Config input file.
-
-=item B<--man>
-
-Print manual page, same as 'perldoc mkpfi'.
-
-=item B<--verbose>
-
-Be verbose!
-
-=back
-
-=head1 BUGS
-
-Report via MTD mailing list
-
-
-=head1 SEE ALSO
-
-http://www.linux-mtd.infradead.org/
-
-
-=head1 AUTHOR
-
-Oliver Lohmann (oliloh@de.ibm.com)
-
-=cut
diff --git a/ubi-utils/perl/ubicrc32.pl b/ubi-utils/perl/ubicrc32.pl
deleted file mode 100755
index add5f9d..0000000
--- a/ubi-utils/perl/ubicrc32.pl
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/perl -w
-
-# Subroutine crc32(): Calculates the CRC on a given string.
-
-{
-    my @table = ();
-
-    # @brief Calculate CRC32 for a given string.
-    sub crc32
-    {
-	unless (@table) {
-	    # Initialize the CRC table
-	    my $poly = 0xEDB88320;
-	    @table = ();
-
-	    for my $i (0..255) {
-		my $c = $i;
-
-		for my $j (0..7) {
-		    $c = ($c & 1) ? (($c >> 1) ^ $poly) : ($c >> 1);
-		}
-		$table[$i] = $c;
-	    }
-	}
-	my $s = shift;		# string to calculate the CRC for
-	my $crc = shift;	# CRC start value
-
-	defined($crc)
-	    or $crc = 0xffffffff; # Default CRC start value
-
-	for (my $i = 0; $i < length($s); $i++) {
-	    $crc = $table[($crc ^ ord(substr($s, $i, 1))) & 0xff]
-		^ ($crc >> 8);
-	}
-	return $crc;
-    }
-}
-
-sub crc32_on_file
-{
-    my $file = shift;
-
-    my $crc32 = crc32('');
-    my $buf = '';
-    my $ret = 0;
-
-    while ($ret = read($file, $buf, 8192)) {
-	$crc32 = crc32($buf, $crc32);
-    }
-    defined($ret)
-	or return undef;
-    printf("0x%x\n", $crc32);
-}
-
-
-# Main routine: Calculate the CRCs on the given files and print the
-# results.
-
-{
-    if (@ARGV) {
-	while (my $path = shift) {
-	    my $file;
-	    open $file, "<", $path
-		or die "Error opening '$path'.\n";
-	    
-	    &crc32_on_file($file)
-		or die "Error reading from '$path'.\n";
-	    close $file;
-	}
-    } else {
-	&crc32_on_file(\*STDIN)
-	    or die "Error reading from stdin.\n";
-    }
-}
diff --git a/ubi-utils/scripts/Makefile b/ubi-utils/scripts/Makefile
deleted file mode 100644
index ebd9bc6..0000000
--- a/ubi-utils/scripts/Makefile
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# Makefile
-#
-# Testcase for UBI pfi update.
-#
-# Author:	Frank Haverkamp <haverkam@de.ibm.com>
-#
-
-card		= test
-mkpfi_cfg	= test.cfg
-
-#
-# Some default values you might want to overwrite. Try it if you need
-# it and add more if needed. Note that no real sanity checking is done
-# on those values. If you do it wrong your card has no valid PDD data.
-#
-
-PATH := $(PATH):/opt/ppc/usr/bin:../perl:..
-
-dd		= dd
-sed		= sed
-bin2nand	= bin2nand
-ubigen		= ubigen
-mkpfi		= mkpfi -v
-pfi2bin		= pfi2bin -v
-
-vmlinux_bin	?= test_vmlinux.bin
-rootfs_bin	?= test_rootfs.bin
-spl_bin		?= test_u-boot.bin
-pdd_txt		?= pdd.txt
-
-flashtype	?= nand
-pagesize	?= 2048
-
-compl		?= $(card)_complete
-compl_pfi	?= $(compl).pfi
-compl_img	?= $(compl).img
-
-compl_nand2048_mif=$(compl).$(flashtype)$(pagesize).mif
-compl_nand2048_img=$(compl).$(flashtype)$(pagesize).img
-
-all: $(compl_pfi) $(compl_nand2048_mif)
-
-$(compl_pfi): $(vmlinux_bin) $(rootfs_bin) $(spl_bin)
-	$(mkpfi) -c $(mkpfi_cfg)
-
-# Binary data and out of band data (OOB)
-#
-$(compl_nand2048_mif): $(compl_img)
-	$(bin2nand) -p $(pagesize) -o $(compl_nand2048_mif) $<
-
-# Binary data only
-#
-$(compl_img): $(compl_pfi)
-	$(pfi2bin) -j $(pdd_txt) -o $@ $<
-
-#
-# Default data
-#
-# If the binary data is not available in the current working directory
-# we try to create symlinks to our test data.
-#
-$(vmlinux_bin) $(rootfs_bin) $(spl_bin):
-	@echo
-	@echo "No $@ found, will use defaults !"
-	@echo
-	@echo "OR press CTRL-C to provide your own $@" && 	\
-	sleep 1 &&						\
-	$(dd) if=/dev/urandom of=$@ bs=1M count=1
-
-clean:
-	$(RM) *.pfi *~
-
-distclean: clean
-	$(RM) *.bin *.mif *.oob *.img
diff --git a/ubi-utils/scripts/README b/ubi-utils/scripts/README
deleted file mode 100644
index 899b4a1..0000000
--- a/ubi-utils/scripts/README
+++ /dev/null
@@ -1,11 +0,0 @@
-README
-======
-
-This procedure creates a test pfi which should be flashed to our
-system with pfiflash. The testcase should read the data back and 
-compare with the original.
-
-We should try not forget to run these tests before we release 
-a new version of UBI.
-
-Frank
diff --git a/ubi-utils/scripts/TODO b/ubi-utils/scripts/TODO
deleted file mode 100644
index f093e77..0000000
--- a/ubi-utils/scripts/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-TODO
-====
-
- * Range checking is broken, reserving 2M and offering 3M binary data
-   ... works!? No!
diff --git a/ubi-utils/scripts/bin2nand2bin_test.sh b/ubi-utils/scripts/bin2nand2bin_test.sh
deleted file mode 100644
index a17c91b..0000000
--- a/ubi-utils/scripts/bin2nand2bin_test.sh
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/bin/sh
-#
-# Testcase for nand2bin and bin2nand. Generate testdata and inject
-# biterrors. Convert data back and compare with original data.
-#
-# Conversion:
-#    bin -> bin2nand -> mif -> nand2bin -> img
-#
-
-inject_biterror=./scripts/inject_biterror.pl
-
-pagesize=2048
-oobsize=64
-
-# Create test data
-dd if=/dev/urandom of=testblock.bin bs=131072 count=1
-
-echo "Test conversion without bitflips ..."
-
-echo -n "Convert bin to mif ... "
-bin2nand --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 --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
-
-echo "Test conversion with uncorrectable ECC erors ..."
-echo -n "Inject biterror at offset $ioffs ... "
-${inject_biterror} --offset=0 --bitmask=0x81 \
-    --input=testblock.mif \
-    --output=testblock_bitflip.mif
-if [ $? -ne "0" ]; then
-    echo "failed!"
-    exit 1
-else
-    echo "ok"
-fi
-
-echo "Convert mif to bin ... "
-rm testblock.img
-nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \
-    testblock_bitflip.mif
-if [ $? -ne "0" ]; then
-    echo "failed!"
-    exit 1
-else
-    echo "ok"
-fi
-
-echo -n "Comparing data, must fail due to uncorrectable ECC ... "
-diff testblock.bin testblock.img
-if [ $? -ne "0" ]; then
-    echo "ok" # Must fail!
-else
-    echo "failed!"
-    exit 1
-fi
-
-echo "Test bitflips in data ... "
-for offs in `seq 0 255` ; do
-
-    cp testblock.mif testblock_bitflip.mif
-
-    for xoffs in 0 256 512 768 ; do
-	let ioffs=$offs+$xoffs
-
-	cp testblock_bitflip.mif testblock_bitflip_tmp.mif
-	echo -n "Inject biterror at offset $ioffs ... "
-	${inject_biterror} --offset=${ioffs} --bitmask=0x01 \
-	    --input=testblock_bitflip_tmp.mif \
-	    --output=testblock_bitflip.mif
-	if [ $? -ne "0" ]; then
-	    echo "failed!"
-	    exit 1
-	else
-	    echo "ok"
-	fi
-    done
-
-    echo "Convert mif to bin ... "
-    rm testblock.img
-    nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \
-	testblock_bitflip.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
-	hexdump testblock.bin > testblock.bin.txt
-	hexdump testblock.img > testblock.img.txt
-	echo "Use tkdiff testblock.bin.txt testblock.img.txt to compare"
-	echo "failed!"
-	exit 1
-    else
-	echo "ok"
-    fi
-
-    # Without correction
-    echo "Convert mif to bin ... "
-    rm testblock.img
-    nand2bin --pagesize=${pagesize} -o testblock.img \
-	testblock_bitflip.mif
-    if [ $? -ne "0" ]; then
-	echo "failed!"
-	exit 1
-    else
-	echo "ok"
-    fi
-
-    echo -n "Comparing data must differ, correction is disabled ... "
-    diff testblock.bin testblock.img
-    if [ $? -ne "0" ]; then
-	echo "ok" # must fail
-    else
-	echo "failed!"
-	exit 1
-    fi
-done
-
-echo "Test bitflips in OOB data ... "
-for offs in `seq 0 $oobsize` ; do
-
-    let ioffs=$pagesize+$offs
-
-    echo -n "Inject biterror at offset $ioffs ... "
-    ${inject_biterror} --offset=${ioffs} --bitmask=0x01 \
-	--input=testblock.mif \
-	--output=testblock_bitflip.mif
-    if [ $? -ne "0" ]; then
-	echo "failed!"
-	exit 1
-    else
-	echo "ok"
-    fi
-
-    echo "Convert mif to bin ... "
-    rm testblock.img
-    nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \
-	testblock_bitflip.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
-	hexdump testblock.bin > testblock.bin.txt
-	hexdump testblock.img > testblock.img.txt
-	echo "Use tkdiff testblock.bin.txt testblock.img.txt to compare"
-	echo "failed!"
-	exit 1
-    else
-	echo "ok"
-    fi
-done
-
diff --git a/ubi-utils/scripts/inject_biterror.pl b/ubi-utils/scripts/inject_biterror.pl
deleted file mode 100644
index b4a862a..0000000
--- a/ubi-utils/scripts/inject_biterror.pl
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/perl -w
-#
-# 2007 Frank Haverkamp <haver@vnet.ibm.com>
-#
-# Program for bit-error injection. I am sure that perl experts do it
-# in 1 line. Please let me know how it is done right ;-).
-#
-
-use strict;
-use warnings;
-use Getopt::Long;
-use Pod::Usage;
-
-my $i;
-my $help;
-my $result;
-my $offset = 0;
-my $bitmask = 0x01;
-my $in = "input.mif";
-my $out = "output.mif";
-
-$result = GetOptions ("offset=i"  => \$offset,    # numeric
-		      "bitmask=o" => \$bitmask,   # numeric
-		      "input=s"	  => \$in,	  # string
-		      "output=s"  => \$out,       # string
-		      "help|?"    => \$help) or pod2usage(2);
-
-pod2usage(1) if $help;
-
-my $buf;
-
-open(my $in_fh, "<", $in)
-  or die "Cannot open file $in: $!";
-binmode $in_fh;
-
-open(my $out_fh, ">", $out) or
-  die "Cannot open file $out: $!";
-binmode $out_fh;
-
-$i = 0;
-while (sysread($in_fh, $buf, 1)) {
-
-	$buf = pack('C', unpack('C', $buf) ^ $bitmask) if ($i == $offset);
-	syswrite($out_fh, $buf, 1) or
-	  die "Cannot write to offset $offset: $!";
-	$i++;
-}
-
-close $in_fh;
-close $out_fh;
-
-__END__
-
-=head1 NAME
-
-inject_biterrors.pl
-
-=head1 SYNOPSIS
-
-inject_biterror.pl [options]
-
-=head1 OPTIONS
-
-=over 8
-
-=item B<--help>
-
-Print a brief help message and exits.
-
-=item B<--offset>=I<offset>
-
-Byte-offset where bit-error should be injected.
-
-=item B<--bitmask>=I<bitmask>
-
-Bit-mask where to inject errors in the byte.
-
-=item B<--input>=I<input-file>
-
-Input file.
-
-=item B<--output>=I<output-file>
-
-Output file.
-
-=back
-
-=head1 DESCRIPTION
-
-B<inject_biterrors.pl> will read the given input file and inject
-biterrors at the I<offset> specified. The location of the biterrors
-are defined by the I<bitmask> parameter.
-
-=cut
diff --git a/ubi-utils/scripts/jffs2_test.sh b/ubi-utils/scripts/jffs2_test.sh
deleted file mode 100755
index 0cc9f0c..0000000
--- a/ubi-utils/scripts/jffs2_test.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/sh
-#
-# Testcase for JFFS2 verification. We do not want to see any
-# kernel errors occuring when this is executed.
-#
-#
-# 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
-}
-
-echo "***********************************************************************"
-echo "*        jffs2 testing ...                                            *"
-echo "***********************************************************************"
-
-ulimit -c unlimited
-
-for i in `seq 5000`; do
-    echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... "
-    dd if=/dev/urandom of=test.bin bs=$i count=1;
-    if [ $? -ne "0" ] ; then
-        exit_failure
-    fi
-    passed
-
-    echo "Copy to different file ... "
-    dd if=test.bin of=new.bin bs=$i count=1;
-    if [ $? -ne "0" ] ; then
-        exit_failure
-    fi
-    passed
-
-    echo "Comparing files ... "
-    cmp test.bin new.bin
-    dd if=test.bin of=new.bin bs=$i count=1;
-    if [ $? -ne "0" ] ; then
-        exit_failure
-    fi
-    passed
-done
-
-for i in `seq 5000`; do
-    echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... "
-    dd if=/dev/urandom of=foo bs=$i count=1;
-    if [ $? -ne "0" ] ; then
-        exit_failure
-    fi
-    passed
-done
-
-for i in `seq 5000`; do 
-    echo "Testing $i byte (dd if=/dev/zero of=foo bs=$i count=1) ... "
-    dd if=/dev/zero of=foo bs=$i count=1;
-    if [ $? -ne "0" ] ; then
-        exit_failure
-    fi
-    passed
-done
-
-echo "***********************************************************************"
-echo "*               Congratulations, no errors found!                     *"
-echo "*              Have fun with your cool JFFS2 using system!            *"
-echo "***********************************************************************"
-
-exit_success
diff --git a/ubi-utils/scripts/mkdevs.pl b/ubi-utils/scripts/mkdevs.pl
deleted file mode 100755
index f0fd464..0000000
--- a/ubi-utils/scripts/mkdevs.pl
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/perl -w
-
-#
-# Author: Artem B. Bityutskiy <dedekind@oktetlabs.ru>
-#
-# A small scrip which creates UBI device nodes in /dev. UBI allocates
-# major number dynamically, so the script looks at /proc/devices to find
-# out UBI's major number.
-#
-
-
-my $proc = '/proc/devices';
-my $regexp = '(\d+) (ubi\d+)$';
-
-
-open FILE, "<", $proc or die "Cannot open $proc file: $!\n";
-my @file = <FILE>;
-close FILE;
-
-foreach (@file) {
-	next if not m/$regexp/g;
-	print "found $2\n";
-
-	system("rm -rf /dev/$2");
-	system("mknod /dev/$2 c $1 0");
-
-	for (my $i = 0; $i < 128; $i += 1) {
-		system("rm -rf /dev/$2_$i");
-		my $j = $i + 1;
-		system("mknod /dev/$2_$i c $1 $j");
-	}
-}
diff --git a/ubi-utils/scripts/pdd.txt b/ubi-utils/scripts/pdd.txt
deleted file mode 100644
index a3ad915..0000000
--- a/ubi-utils/scripts/pdd.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-pdd=flash_type,flash_size,flash_eraseblock_size,flash_page_size,card_serialnumber,card_type,ethaddr,eth1addr,eth0,eth1,total,card_hardwarelevel
-pdd_preserve=ethaddr,eth1addr,card_serialnumber
-# To be personalized
-ethaddr=00:04:34:56:78:9A
-eth1addr=00:04:34:56:78:9B
-card_serialnumber=SN0
-# Static for this card type
-total=102M
-card_type=nand_driven_testcard
-card_hardwarelevel=0
-eth0=bcm5222,eth0,0
-eth1=bcm5222,eth0,1
-flash_type=NAND
-flash_size=0x08000000
-flash_eraseblock_size=0x00020000
-flash_page_size=0x00000800
diff --git a/ubi-utils/scripts/run_all.sh b/ubi-utils/scripts/run_all.sh
deleted file mode 100755
index 040bcbd..0000000
--- a/ubi-utils/scripts/run_all.sh
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/bin/sh
-
-exit_success ()
-{
-	echo "UBI Utils Test Scripts - SUCCESS!"
-	exit 0
-}
-
-exit_failure ()
-{
-	echo $1
-	echo "UBI Utils Test Scripts - FAILED!"
-	exit 1
-}
-
-echo UBI Utils Test Scripts
-
-devno=$1
-logfile=temp-test-log.txt
-
-if test -z "$devno";
-then
-	echo "Usage is $0 <mtd device number>"
-	exit 1
-fi
-
-cwd=`pwd` || exit_failure "pwd failed"
-
-log="${cwd}/${logfile}"
-
-PATH=$PATH:$cwd:..
-
-cat /dev/null > $log || exit_failure "Failed to create $log"
-
-echo "Setting up for jffs2_test.sh" | tee -a $log
-
-avail=`cat /sys/class/ubi/ubi${devno}/avail_eraseblocks`
-size=`cat /sys/class/ubi/ubi${devno}/eraseblock_size`
-
-bytes=`expr $avail \* $size`
-
-ubimkvol -d$devno -s$bytes -n0 -Njtstvol || exit_failure "ubimkvol failed"
-
-mkdir -p /mnt/test_file_system || exit_failure "mkdir failed"
-
-mtd=`cat /proc/mtd | grep jtstvol | cut -d: -f1`
-
-if test -z "$mtd";
-then
-	exit_failure "mtd device not found"
-fi
-
-mount -t jffs2 $mtd /mnt/test_file_system || exit_failure "mount failed"
-
-cd /mnt/test_file_system || exit_failure "cd failed"
-
-echo Running jffs2_test.sh | tee -a $log
-
-jffs2_test.sh >> $log 2>&1 || exit_failure "jffs2_test.sh failed"
-
-rm -f *
-
-cd $cwd || exit_failure "cd failed"
-
-umount /mnt/test_file_system || exit_failure "umount failed"
-
-ubirmvol -d$devno -n0 || exit_failure "ubirmvol failed"
-
-major=`cat /sys/class/ubi/ubi${devno}/dev | cut -d: -f1`
-
-for minor in `seq 0 32`; do
-	if test ! -e /dev/ubi${devno}_$minor ;
-	then
-		mknod /dev/ubi${devno}_$minor c $major $(($minor + 1))
-	fi
-done
-
-rm -f testdata.bin readdata.bin
-
-echo Running ubi_jffs2_test.sh | tee -a $log
-
-ubi_jffs2_test.sh >> $log 2>&1 || exit_failure "ubi_jffs2_test.sh failed"
-
-echo Running ubi_test.sh | tee -a $log
-
-ubi_test.sh >> $log 2>&1 || exit_failure "ubi_test.sh failed"
-
-for minor in `seq 0 32`; do
-	if test -e /sys/class/ubi/ubi${devno}/$minor;
-	then
-		ubirmvol -d$devno -n$minor || exit_failure "ubirmvol failed"
-	fi
-done
-
-echo Running ubi_tools_test.sh | tee -a $log
-
-ubi_tools_test.sh >> $log 2>&1 || exit_failure "ubi_tools_test failed"
-
-rm -f $log
-
-exit_success
diff --git a/ubi-utils/scripts/test.cfg b/ubi-utils/scripts/test.cfg
deleted file mode 100644
index 0b5ec48..0000000
--- a/ubi-utils/scripts/test.cfg
+++ /dev/null
@@ -1,23 +0,0 @@
-[targets]
-test_complete=spl,kernel,rootfs
-
-[spl]
-image=test_u-boot.bin
-ubi_ids=10,11
-ubi_size=1MiB 
-ubi_type=static
-ubi_names=test_spl_0,test_spl_1
-
-[kernel]
-image=test_vmlinux.bin
-ubi_ids=12,13
-ubi_size=2MiB 
-ubi_type=static
-ubi_names=test_kernel_0,test_kernel_1
-
-[rootfs]
-image=test_rootfs.bin
-ubi_ids=14,15
-ubi_size=2MiB 
-ubi_type=dynamic
-ubi_names=test_rootfs_0,test_rootfs_1
diff --git a/ubi-utils/scripts/ubi_jffs2_test.sh b/ubi-utils/scripts/ubi_jffs2_test.sh
deleted file mode 100755
index 883903d..0000000
--- a/ubi-utils/scripts/ubi_jffs2_test.sh
+++ /dev/null
@@ -1,411 +0,0 @@
-#!/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/scripts/ubi_test.sh b/ubi-utils/scripts/ubi_test.sh
deleted file mode 100755
index 73e4b19..0000000
--- a/ubi-utils/scripts/ubi_test.sh
+++ /dev/null
@@ -1,328 +0,0 @@
-#!/bin/sh
-#
-# UBI Volume creation/deletion/write/read test script
-#
-# 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 Use ubiupdatevol instead of ubiwritevol
-#
-
-VERSION="1.1"
-
-export PATH=$PATH:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/
-
-UBIMKVOL=ubimkvol
-UBIRMVOL=ubirmvol
-UBIUPDATEVOL=ubiupdatevol
-
-# 128 KiB 131072
-# 256 KiB 262144
-# 512 KiB 524288
-
-SIZE_512K=524288
-SIZE_1M=1310720
-
-SELF=$0
-MINVOL=10
-MAXVOL=12
-
-#
-# 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 -n "*** 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 0 $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
-}
-
-# 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 -n "*** Truncate volume if it exists ... "
-	$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
-    fi
-}
-
-mkvol_rmvol_test ()
-{
-    type=$1
-
-### Test if volume delete on non-existing volumes fails nicely
-
-    for i in `seq $MINVOL $MAXVOL`; do
-	echo "*** Delete if exist or not $i ... "
-
-	delete_volume $i
-	passed
-    done
-
-### Now deleting volumes must fail
-
-    for i in `seq $MINVOL $MAXVOL`; do
-	echo "*** Trying to delete non existing UBI Volume $i ... "
-
-	$UBIRMVOL -d0 -n$i
-	if [ $? -eq "0" ] ; then
-	    exit_failure
-	fi
-	passed
-    done
-
-### Test if volume creation works ok
-
-    for i in `seq $MINVOL $MAXVOL`; do
-	echo "*** Creating UBI Volume $i ... "
-	echo "    $UBIMKVOL -d0 -n$i -t$type -NNEW$i -s $SIZE_512K"
-
-	$UBIMKVOL -d0 -n$i -t$type -N"NEW$i" -s $SIZE_512K
-	if [ $? -ne "0" ] ; then
-	    exit_failure
-	fi
-	passed
-    done
-
-### Now deleting volumes must be ok
-
-    for i in `seq $MINVOL $MAXVOL`; do
-	echo "*** Trying to delete UBI Volume $i ... "
-
-	$UBIRMVOL -d0 -n$i
-	if [ $? -ne "0" ] ; then
-	    exit_failure
-	fi
-	passed
-    done
-
-### Now allocate too large volume
-
-    echo -n "*** Try to create too large volume"
-    $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s 800000000
-    if [ $? -eq "0" ] ; then
-	exit_failure
-    fi
-    passed
-}
-
-# writevol_test - Tests volume creation and writing data to it.
-#
-# @size:    Size of random data to write
-# @type:    Volume type static or dynamic
-#
-writevol_test ()
-{
-    size=$1
-    type=$2
-
-    echo "*** Write volume test with size $size"
-
-### Make sure that volume exist, delete existing volume, create new
-
-    delete_volume $MINVOL
-
-    echo -n "*** Try to create volume ... "
-    $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s $SIZE_1M
-    if [ $? -ne "0" ] ; then
-	exit_failure
-    fi
-    passed
-    
-### Try to create same volume again
-    echo -n "*** Try to create some volume again, this must fail ... "
-    $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s $SIZE_1M
-    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 ... "
-    # sleep 5
-    ls -l testdata.bin
-    echo "    $UBIUPDATEVOL -d0 -n$MINVOL testdata.bin"
-    $UBIUPDATEVOL -d0 -n$MINVOL testdata.bin
-    if [ $? -ne "0" ] ; then
-	exit_failure
-    fi
-    passed
-
-    if [ $type = "static" ] ; then
-	echo "*** Download data with cat ... "
-	cat /dev/ubi0_$MINVOL > readdata.bin
-	if [ $? -ne "0" ] ; then
-	    exit_failure
-	fi
-	passed
-    else
-	echo "*** Download data with dd bs=1 ... "
-	dd if=/dev/ubi0_$MINVOL of=readdata.bin bs=$size count=1
-	if [ $? -ne "0" ] ; then
-	    exit_failure
-	fi
-	passed
-
-	# Size 1 does not work with this test ...
-	#
-	#echo "*** Download data with dd bs=$size ... "
-	#dd if=/dev/ubi0_$MINVOL of=readdata2.bin bs=$size count=1
-	#if [ $? -ne "0" ] ; then
-	#    exit_failure
-	#fi
-	#passed
-
-	#echo -n "*** Comparing data (1) ... "
-	#cmp readdata.bin readdata2.bin
-	#if [ $? -ne "0" ] ; then
-	#    exit_failure
-	#fi
-	#passed
-    fi
-
-    echo -n "*** Comparing data ... "
-    cmp readdata.bin testdata.bin
-    if [ $? -ne "0" ] ; then
-	exit_failure
-    fi
-    passed
-}
-
-echo "***********************************************************************"
-echo "*           UBI Testing starts now ...                                *"
-echo "*                                 Good luck!                          *"
-echo "***********************************************************************"
-
-# 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
-
-echo "***********************************************************************"
-echo "*        mkvol/rmvol testing for static volumes ...                   *"
-echo "***********************************************************************"
-
-mkvol_rmvol_test static
-
-echo "***********************************************************************"
-echo "*        mkvol/rmvol testing for dynamic volumes ...                  *"
-echo "***********************************************************************"
-
-mkvol_rmvol_test dynamic
-
-echo "***********************************************************************"
-echo "*                write to static volumes ...                          *"
-echo "***********************************************************************"
-
-# 10 Erase blocks = (128 KiB - 64 * 2) * 10
-#                 = 1309440 bytes
-# 128 KiB 131072
-# 256 KiB 262144
-# 512 KiB 524288
-
-for size in 262144 131073 131072 2048 1 4096 12800 31313  ; do
-    writevol_test $size static
-done
-
-echo "***********************************************************************"
-echo "*                write to dynamic volumes ...                         *"
-echo "***********************************************************************"
-echo "VERSION: $VERSION"
-
-for size in 131073 131072 2048 1 4096 12800 31313 262144 ; do
-    writevol_test $size dynamic
-done
-
-echo "***********************************************************************"
-echo "*               Congratulations, no errors found!                     *"
-echo "*              Have fun with your cool UBI system!                    *"
-echo "***********************************************************************"
-
-exit_success
diff --git a/ubi-utils/scripts/ubi_tools_test.sh b/ubi-utils/scripts/ubi_tools_test.sh
deleted file mode 100755
index 7f121f1..0000000
--- a/ubi-utils/scripts/ubi_tools_test.sh
+++ /dev/null
@@ -1,252 +0,0 @@
-#!/bin/sh
-#
-# UBI Volume creation/deletion/write/read test script.
-# Uses our flash update tools and the associated toolchain for flash
-# image creation.
-#
-# 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
-#
-
-VERSION="1.0"
-
-export PATH=$PATH:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/
-
-UBIMKVOL=ubimkvol
-UBIRMVOL=ubirmvol
-UBIWRITEVOL=ubiupdatevol
-PFIFLASH=pfiflash
-CMP=cmp
-
-MAXVOL=32
-
-test_pfi=test_complete.pfi
-real_pfi=example_complete.pfi
-
-# 128 KiB 131072
-# 256 KiB 262144
-# 512 KiB 524288
-
-#
-# 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 -n "*** 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 0 $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
-}
-
-# 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 -n "*** Truncate volume if it exists ... "
-	$UBIWRITEVOL -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
-    fi
-}
-
-echo "***********************************************************************"
-echo "*           UBI Tools Testing starts now ...                          *"
-echo "*                                 Good luck!                          *"
-echo "***********************************************************************"
-
-# 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 other hardware"
-fi
-
-### Test basic stuff
-pfiflash_basic ()
-{
-    echo "Calling pfiflash with test-data ... "
-    echo "    $PFIFLASH $test_pfi"
-    $PFIFLASH $test_pfi
-    if [ $? -ne "0" ]; then
-	echo "Uhhh something went wrong!"
-	exit_failure
-    fi
-    passed
-    
-    echo "Testing if data is correct 10 and 11 ... "
-    $CMP /dev/ubi0_10 /dev/ubi0_11
-    if [ $? -ne "0" ]; then
-	echo "Mirrored volumes not equal!"
-	exit_failure
-    fi
-    passed
-    
-    echo "Comparing against original data ... "
-    $CMP /dev/ubi0_10 test_u-boot.bin
-    if [ $? -ne "0" ]; then
-	echo "Compared volume not equal!"
-	exit_failure
-    fi
-    passed
-    
-    echo "Testing if data is correct 12 and 13 ... "
-    $CMP /dev/ubi0_12 /dev/ubi0_13
-    if [ $? -ne "0" ]; then
-	echo "Mirrored volumes not equal!"
-	exit_failure
-    fi
-    passed
-    
-    echo "Comparing against original data ... "
-    $CMP /dev/ubi0_12 test_vmlinux.bin
-    if [ $? -ne "0" ]; then
-	echo "Compared volume not equal!"
-	exit_failure
-    fi
-    passed
-    
-    echo "Testing if data is correct 14 and 15 ... "
-    $CMP /dev/ubi0_14 /dev/ubi0_15
-    if [ $? -ne "0" ]; then
-	echo "Mirrored volumes not equal!"
-	exit_failure
-    fi
-    passed
-}
-
-### Test each and everything
-pfiflash_advanced ()
-{
-    if [ -e  example_complete.pfi ]; then
-	echo "Calling pfiflash with real data ... "
-	$PFIFLASH -p overwrite --complete example_complete.pfi
-	if [ $? -ne "0" ]; then
-	    echo "Uhhh something went wrong!"
-	    exit_failure
-	fi
-	passed
-	
-	echo "Testing if data is correct 2 and 3 ... "
-	$CMP /dev/ubi0_2 /dev/ubi0_3
-	if [ $? -ne "0" ]; then
-	    echo "Mirrored volumes not equal!"
-	    exit_failure
-	fi
-	passed
-	
-	echo "Comparing against original data ... "
-	$CMP /dev/ubi0_2 u-boot.bin
-	if [ $? -ne "0" ]; then
-	    echo "Compared volume not equal!"
-	    exit_failure
-	fi
-	passed
-	
-	echo "Testing if data is correct 6 and 7 ... "
-	$CMP /dev/ubi0_6 /dev/ubi0_7
-	if [ $? -ne "0" ]; then
-	    echo "Mirrored volumes not equal!"
-	    exit_failure
-	fi
-	passed
-	
-	echo "Comparing against original data ... "
-	$CMP /dev/ubi0_6 vmlinux.bin
-	if [ $? -ne "0" ]; then
-	    echo "Compared volume not equal!"
-	    exit_failure
-	fi
-	passed
-    fi
-}
-
-echo "***********************************************************************"
-echo "*                Testing pfiflash ...                                 *"
-echo "***********************************************************************"
-echo "VERSION: $VERSION"
-
-pfiflash_basic
-pfiflash_advanced
-    
-echo "***********************************************************************"
-echo "*               Congratulations, no errors found!                     *"
-echo "*              Have fun with your cool UBI system!                    *"
-echo "***********************************************************************"
-
-exit_success
diff --git a/ubi-utils/scripts/unubi_test.sh b/ubi-utils/scripts/unubi_test.sh
deleted file mode 100644
index 40dc2e2..0000000
--- a/ubi-utils/scripts/unubi_test.sh
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/bin/sh
-#
-# Use raw NAND data, extract UBI image and apply tool to it.
-# Test basic functionality.
-#
-# 2007 Frank Haverkamp <haver@vnet.ibm.com>
-#
-
-version=1.1
-
-image=data.mif
-oob=oob.bin
-data=data.bin
-pagesize=2048
-volmax=31
-datadir=unubi_data
-
-# general arguments e.g. debug enablement
-# unubi_args="-D"
-
-echo "------------------------------------------------------------------------"
-echo "Testcase: ${0} Version: ${version}"
-echo "------------------------------------------------------------------------"
-echo "Testing nand2bin ..."
-echo "  Input:    ${image}"
-echo "  Data:     ${data}"
-echo "  OOB:      ${oob}"
-echo "  Pagesize: ${pagesize}"
-nand2bin --pagesize ${pagesize} -o ${data} -O ${oob} ${image}
-echo
-
-echo "------------------------------------------------------------------------"
-echo "Testing unubi ..."
-echo "------------------------------------------------------------------------"
-unubi --version
-echo
-
-echo "------------------------------------------------------------------------"
-echo "Trying to extract first ${volmax} volumes ..."
-echo "------------------------------------------------------------------------"
-mkdir -p ${datadir}/volumes
-for v in `seq 0 ${volmax}` ; do
-    unubi ${unubi_args} -r${v} -d${datadir}/volumes ${data}
-    echo -n "."
-done
-echo "ok"
-ls -l ${datadir}/volumes
-echo
-
-echo "------------------------------------------------------------------------"
-echo "Extracting graphics ..."
-echo "------------------------------------------------------------------------"
-unubi -a  -d${datadir} ${data}
-echo "Use gnuplot to display:"
-ls ${datadir}/*.plot
-ls ${datadir}/*.data
-echo
-
-echo "------------------------------------------------------------------------"
-echo "eb-split"
-echo "------------------------------------------------------------------------"
-unubi -e -d${datadir}/eb-split ${data}
-ls -l ${datadir}/eb-split
-echo
-
-echo "------------------------------------------------------------------------"
-echo "vol-split"
-echo "------------------------------------------------------------------------"
-unubi -v -d${datadir}/vol-split ${data}
-ls  -l ${datadir}/vol-split
-echo
-echo "The generated images contain only the data (126KiB in our   "
-echo "case) not including the UBI erase count and volume info     "
-echo "header. For dynamic volumes the data should be the full     "
-echo "126KiB. Unubi cannot know how much of the data is valid.    "
-echo
-
-echo "------------------------------------------------------------------------"
-echo "!vol-split"
-echo "------------------------------------------------------------------------"
-unubi -V -d${datadir}/vol-split! ${data}
-ls -l ${datadir}/vol-split\!
-echo
-echo "The generated images contain the full block data of 128KiB  "
-echo "including the UBI erase count and volume information header."
-echo
-
-echo "------------------------------------------------------------------------"
-echo "Extracting volume info table ..."
-echo "------------------------------------------------------------------------"
-unubi -i -d${datadir} ${data}
-echo "I strongly hope that empty ubi blocks are filled with 0xff! "
-echo
-
-echo "------------------------------------------------------------------------"
-echo "Table 0"
-echo "------------------------------------------------------------------------"
-cat ${datadir}/vol_info_table0
-echo
-
-echo "------------------------------------------------------------------------"
-echo "Table 1"
-echo "------------------------------------------------------------------------"
-cat ${datadir}/vol_info_table1
-echo
diff --git a/ubi-utils/src/bin2nand.c b/ubi-utils/src/bin2nand.c
deleted file mode 100644
index c7c7ccc..0000000
--- a/ubi-utils/src/bin2nand.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * 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.
- *
- * Author: Oliver Lohmann
- */
-
-/*
- * Create a flashable NAND image from a binary image
- *
- * History:
- * 1.0 Initial release (tglx)
- * 1.1 Understands hex and dec input parameters (tglx)
- * 1.2 Generates separated OOB data, if needed. (oloh)
- * 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)
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include "error.h"
-#include "config.h"
-#include "nandecc.h"
-
-#define PROGRAM_VERSION "1.6"
-
-#define CHECK_ENDP(option, endp) do {			\
-	if (*endp) {					\
-		fprintf(stderr,				\
-			"Parse error option \'%s\'. "	\
-			"No correct numeric value.\n"	\
-			, option);			\
-		exit(EXIT_FAILURE);			\
-	}						\
-} while(0)
-
-typedef enum action_t {
-	ACT_NORMAL	    = 0x00000001,
-} action_t;
-
-#define PAGESIZE	2048
-#define PADDING		   0 /* 0 means, do not adjust anything */
-#define BUFSIZE		4096
-
-static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
-	"bin2nand - a tool for adding OOB information to a "
-	"binary input file.\n";
-
-static const char *optionsstr =
-"  -c, --copyright          Print copyright informatoin.\n"
-"  -j, --padding=<num>      Padding in Byte/Mi/ki. Default = no padding\n"
-"  -p, --pagesize=<num>     Pagesize in Byte/Mi/ki. Default = 2048\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"
-"      --usage              Give a short usage message\n"
-"  -V, --version            Print program version\n";
-
-static const char *usage =
-"Usage: bin2nand [-c?V] [-j <num>] [-p <num>] [-o <fname>] [-q <fname>]\n"
-"            [--copyright] [--padding=<num>] [--pagesize=<num>]\n"
-"            [--output=<fname>] [--output-oob=<fname>] [--help] [--usage]\n"
-"            [--version]\n";
-
-struct option long_options[] = {
-	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
-	{ .name = "padding", .has_arg = 1, .flag = NULL, .val = 'j' },
-	{ .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 = "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}
-};
-
-static const char copyright [] __attribute__((unused)) =
-	"Copyright IBM Corp. 2006";
-
-typedef struct myargs {
-	action_t action;
-
-	size_t pagesize;
-	size_t padding;
-
-	FILE* fp_in;
-	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)
-{
-	unsigned long long res = strtoull(cp, endp, base);
-
-	switch (**endp) {
-	case 'G':
-		res *= 1024;
-	case 'M':
-		res *= 1024;
-	case 'k':
-	case 'K':
-		res *= 1024;
-	/* "Ki", "ki", "Mi" or "Gi" are to be used. */
-		if ((*endp)[1] == 'i')
-			(*endp) += 2;
-	}
-	return res;
-}
-
-static int
-parse_opt(int argc, char **argv, myargs *args)
-{
-	char* endp;
-
-	while (1) {
-		int key;
-
-		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 '?': /* 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);
-		}
-	}
-
-	if (optind < argc) {
-		args->fp_in = fopen(argv[optind++], "rb");
-		if ((args->fp_in) == NULL) {
-			err_quit("Cannot open file %s for input\n",
-				 argv[optind++]);
-		}
-	}
-
-	return 0;
-}
-
-static int
-process_page(uint8_t* buf, size_t pagesize,
-	FILE *fp_data, FILE* fp_oob, size_t* written)
-{
-	int eccpoi, oobsize;
-	size_t i;
-	uint8_t oobbuf[64];
-
-	memset(oobbuf, 0xff, sizeof(oobbuf));
-
-	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, pagesize, fp_data);
-
-	/* either separate oob or interleave with data */
-	if (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, oobsize, fp_data);
-		if (ferror(fp_data)) {
-			err_msg("IO error\n");
-			return -EIO;
-		}
-	}
-
-	return 0;
-}
-
-int main (int argc, char** argv)
-{
-	int rc = -1;
-	int res = 0;
-	size_t written = 0, read;
-	myargs args = {
-		.action	  = ACT_NORMAL,
-		.pagesize = PAGESIZE,
-		.padding  = PADDING,
-		.fp_in	  = NULL,
-		.file_out_data = NULL,
-		.file_out_oob = NULL,
-	};
-
-	FILE* fp_out_data = stdout;
-	FILE* fp_out_oob = NULL;
-
-	parse_opt(argc, argv, &args);
-
-	uint8_t* buf = calloc(1, BUFSIZE);
-	if (!buf) {
-		err_quit("Cannot allocate page buffer.\n");
-	}
-
-	if (!args.fp_in) {
-		err_msg("No input image specified!\n");
-		goto err;
-	}
-
-	if (args.file_out_data) {
-		fp_out_data = fopen(args.file_out_data, "wb");
-		if (fp_out_data == NULL) {
-			err_sys("Cannot open file %s for output\n",
-					args.file_out_data);
-			goto err;
-		}
-	}
-
-	if (args.file_out_oob) {
-		fp_out_oob = fopen(args.file_out_oob, "wb");
-		if (fp_out_oob == NULL) {
-			err_sys("Cannot open file %s for output\n",
-					args.file_out_oob);
-			goto err;
-		}
-	}
-
-
-	while(1) {
-		read = fread(buf, 1, args.pagesize, args.fp_in);
-		if (feof(args.fp_in) && read == 0)
-			break;
-
-		if (read < args.pagesize) {
-			err_msg("Image not page aligned\n");
-			goto err;
-		}
-
-		if (ferror(args.fp_in)) {
-			err_msg("Read error\n");
-			goto err;
-		}
-
-		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(buf, args.pagesize, fp_out_data,
-				fp_out_oob, &written);
-		if (res != 0)
-			goto err;
-	}
-
-	rc = 0;
-err:
-	free(buf);
-
-	if (args.fp_in)
-		fclose(args.fp_in);
-
-	if (fp_out_oob)
-		fclose(fp_out_oob);
-
-	if (fp_out_data && fp_out_data != stdout)
-		fclose(fp_out_data);
-
-	if (rc != 0) {
-		err_msg("Error during conversion. rc: %d\n", rc);
-		if (args.file_out_data)
-			remove(args.file_out_data);
-		if (args.file_out_oob)
-			remove(args.file_out_oob);
-	}
-	return rc;
-}
diff --git a/ubi-utils/src/bootenv.c b/ubi-utils/src/bootenv.c
deleted file mode 100644
index 78198fe..0000000
--- a/ubi-utils/src/bootenv.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2008
- *
- * 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
- */
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <sys/stat.h>
-#include <bootenv.h>
-
-#include "hashmap.h"
-#include "error.h"
-
-#include <mtd/ubi-media.h>
-#include "crc32.h"
-
-#define ubi_unused __attribute__((unused))
-
-#define BOOTENV_MAXLINE 512 /* max line size of a bootenv.txt file */
-
-/* Structures */
-struct bootenv {
-	hashmap_t map;	 ///< Pointer to hashmap which holds data structure.
-};
-
-struct bootenv_list {
-	hashmap_t head; ///< Pointer to list which holds the data structure.
-};
-
-/**
- * @brief Remove the '\n' from a given line.
- * @param line	Input/Output line.
- * @param size	Size of the line.
- * @param fp	File Pointer.
- * @return 0
- * @return or error
- */
-static int
-remove_lf(char *line, size_t size, FILE* fp)
-{
-	size_t i;
-
-	for (i = 0; i < size; i++) {
-		if (line[i] == '\n') {
-			line[i] = '\0';
-			return 0;
-		}
-	}
-
-	if (!feof(fp)) {
-		return BOOTENV_EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- * @brief Determine if a line contains only WS.
- * @param line The line to process.
- * @param size Size of input line.
- * @return 1	Yes, only WS.
- * @return 0	No, contains data.
- */
-static int
-is_ws(const char *line, size_t size)
-{
-	size_t i = 0;
-
-	while (i < size) {
-		switch (line[i]) {
-			case '\n':
-				return 1;
-			case '#':
-				return 1;
-			case ' ':
-				i++;
-				continue;
-			case '\t':
-				i++;
-				continue;
-			default: /* any other char -> no cmnt */
-				return 0;
-		}
-	}
-
-	return 0;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-/**
- * @brief Build a list from a comma seperated value string.
- * @param list	Pointer to hashmap structure which shall store
- *		the list.
- * @param value	Comma seperated value string.
- * @return 0
- * @return or error.
- */
-static int
-build_list_definition(hashmap_t list, const char *value)
-{
-	int rc = 0;
-	char *str = NULL;
-	char *ptr = NULL;
-	size_t len, i, j;
-
-	/* str: val1,val2 , val4,...,valN     */
-	len = strlen(value);
-	str = (char*) malloc((len+1) * sizeof(char));
-
-	/* 1. reformat string: remove spaces */
-	for (i = 0, j = 0; i < len; i++) {
-		if (value[i] == ' ')
-			continue;
-
-		str[j] = value[i];
-		j++;
-	}
-	str[j] = '\0';
-
-	/* str: val1,val2,val4,...,valN\0*/
-	/* 2. replace ',' seperator with '\0' */
-	len = strlen(str);
-	for (i = 0; i < len; i++) {
-		if (str[i] == ',') {
-			str[i] = '\0';
-		}
-	}
-
-	/* str: val1\0val2\0val4\0...\0valN\0*/
-	/* 3. insert definitions into a hash map, using it like a list */
-	i = j = 0;
-	ptr = str;
-	while (((i = strlen(ptr)) > 0) && (j < len)) {
-		rc = hashmap_add(list, ptr, "");
-		if (rc != 0) {
-			free(str);
-			return rc;
-		}
-		j += i+1;
-		if (j < len)
-			ptr += i+1;
-	}
-
-	free(str);
-	return rc;
-}
-
-/**
- * @brief Extract a key value pair and add it to a hashmap
- * @param str	Input string which contains a key value pair.
- * @param env	The updated handle which contains the new pair.
- * @return 0
- * @return or error
- * @note The input string format is: "key=value"
- */
-static int
-extract_pair(const char *str, bootenv_t env)
-{
-	int rc = 0;
-	char *key = NULL;
-	char *val = NULL;
-
-	key = strdup(str);
-	if (key == NULL)
-		return -ENOMEM;
-
-	val = strstr(key, "=");
-	if (val == NULL) {
-		rc = BOOTENV_EBADENTRY;
-		goto err;
-	}
-
-	*val = '\0'; /* split strings */
-	val++;
-
-	rc = bootenv_set(env, key, val);
-
- err:
-	free(key);
-	return rc;
-}
-
-int
-bootenv_destroy(bootenv_t* env)
-{
-	int rc = 0;
-
-	if (env == NULL || *env == NULL)
-		return -EINVAL;
-
-	bootenv_t tmp = *env;
-
-	rc = hashmap_free(tmp->map);
-	if (rc != 0)
-		return rc;
-
-	free(tmp);
-	return rc;
-}
-
-int
-bootenv_create(bootenv_t* env)
-{
-	bootenv_t res;
-	res = (bootenv_t) calloc(1, sizeof(struct bootenv));
-
-	if (res == NULL)
-		return -ENOMEM;
-
-	res->map = hashmap_new();
-
-	if (res->map == NULL) {
-		free(res);
-		return -ENOMEM;
-	}
-
-	*env = res;
-
-	return 0;
-}
-
-
-/**
- * @brief Read a formatted buffer and scan it for valid bootenv
- *	  key/value pairs. Add those pairs into a hashmap.
- * @param env	Hashmap which shall be used to hold the data.
- * @param buf	Formatted buffer.
- * @param size	Size of the buffer.
- * @return 0
- * @return or error
- */
-static int
-rd_buffer(bootenv_t env, const char *buf, size_t size)
-{
-	const char *curr = buf;		/* ptr to current key/value pair */
-	uint32_t i, j;			/* current length, chars processed */
-
-	if (buf[size - 1] != '\0')	/* must end in '\0' */
-		return BOOTENV_EFMT;
-
-	for (j = 0; j < size; j += i, curr += i) {
-		/* strlen returns the size of the string upto
-		   but not including the null terminator;
-		   adding 1 to account for '\0' */
-		i = strlen(curr) + 1;
-
-		if (i == 1)
-			return 0;	/* no string found */
-
-		if (extract_pair(curr, env) != 0)
-			return BOOTENV_EINVAL;
-	}
-
-	return 0;
-}
-
-
-int
-bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t* ret_crc)
-{
-	int rc;
-	char *buf = NULL;
-	size_t i = 0;
-	uint32_t crc32_table[256];
-
-	if ((fp == NULL) || (env == NULL))
-		return -EINVAL;
-
-	/* allocate temp buffer */
-	buf = (char*) calloc(1, size * sizeof(char));
-	if (buf == NULL)
-		return -ENOMEM;
-
-	/* FIXME Andreas, please review this I removed size-1 and
-	 * replaced it by just size, I saw the kernel image starting
-	 * with a 0x0060.... and not with the 0x60.... what it should
-	 * be. Is this a tools problem or is it a problem here where
-	 * fp is moved not to the right place due to the former size-1
-	 * here.
-	 */
-	while((i < size) && (!feof(fp))) {
-		int c = fgetc(fp);
-		if (c == EOF) {
-			/* FIXME isn't this dangerous, to update
-			   the boot envs with incomplete data? */
-			buf[i++] = '\0';
-			break;	/* we have enough */
-		}
-		if (ferror(fp)) {
-			rc = -EIO;
-			goto err;
-		}
-
-		buf[i++] = (char)c;
-	}
-
-	/* calculate crc to return */
-	if (ret_crc != NULL) {
-		init_crc32_table(crc32_table);
-		*ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size);
-	}
-
-	/* transfer to hashmap */
-	rc = rd_buffer(env, buf, size);
-
-err:
-	free(buf);
-	return rc;
-}
-
-
-/**
- * If we have a single file containing the boot-parameter size should
- * be specified either as the size of the file or as BOOTENV_MAXSIZE.
- * If the bootparameter are in the middle of a file we need the exact
- * length of the data.
- */
-int
-bootenv_read(FILE* fp, bootenv_t env, size_t size)
-{
-	return bootenv_read_crc(fp, env, size, NULL);
-}
-
-
-int
-bootenv_read_txt(FILE* fp, bootenv_t env)
-{
-	int rc = 0;
-	char *buf = NULL;
-	char *line = NULL;
-	char *lstart = NULL;
-	char *curr = NULL;
-	size_t len;
-	size_t size;
-
-	if ((fp == NULL) || (env == NULL))
-		return -EINVAL;
-
-	size = BOOTENV_MAXSIZE;
-
-	/* allocate temp buffers */
-	buf = (char*) calloc(1, size * sizeof(char));
-	lstart = line = (char*) calloc(1, size * sizeof(char));
-	if ((buf == NULL)  || (line == NULL)) {
-		rc = -ENOMEM;
-		goto err;
-	}
-
-	curr = buf;
-	while ((line = fgets(line, size, fp)) != NULL) {
-		if (is_ws(line, size)) {
-			continue;
-		}
-		rc = remove_lf(line, BOOTENV_MAXSIZE, fp);
-		if (rc != 0) {
-			goto err;
-		}
-
-		/* copy new line to binary buffer */
-		len = strlen(line);
-		if (len > size) {
-			rc = -EFBIG;
-			goto err;
-		}
-		size -= len; /* track remaining space */
-
-		memcpy(curr, line, len);
-		curr += len + 1; /* for \0 seperator */
-	}
-
-	rc = rd_buffer(env, buf, BOOTENV_MAXSIZE);
-err:
-	if (buf != NULL)
-		free(buf);
-	if (lstart != NULL)
-		free(lstart);
-	return rc;
-}
-
-static int
-fill_output_buffer(bootenv_t env, char *buf, size_t buf_size_max ubi_unused,
-		size_t *written)
-{
-	int rc = 0;
-	size_t keys_size, i;
-	size_t wr = 0;
-	const char **keys = NULL;
-	const char *val = NULL;
-
-	rc = bootenv_get_key_vector(env, &keys_size, 1, &keys);
-	if (rc != 0)
-		goto err;
-
-	for (i = 0; i < keys_size; i++) {
-		if (wr > BOOTENV_MAXSIZE) {
-			rc = -ENOSPC;
-			goto err;
-		}
-
-		rc = bootenv_get(env, keys[i], &val);
-		if (rc != 0)
-			goto err;
-
-		wr += snprintf(buf + wr, BOOTENV_MAXSIZE - wr,
-				"%s=%s", keys[i], val);
-		wr++; /* for \0 */
-	}
-
-	*written = wr;
-
-err:
-	if (keys != NULL)
-		free(keys);
-
-	return rc;
-}
-
-int
-bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc)
-{
-	int rc = 0;
-	size_t size = 0;
-	char *buf = NULL;
-	uint32_t crc32_table[256];
-
-	if ((fp == NULL) || (env == NULL))
-		return -EINVAL;
-
-	buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char));
-	if (buf == NULL)
-		return -ENOMEM;
-
-
-	rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, &size);
-	if (rc != 0)
-		goto err;
-
-	/* calculate crc to return */
-	if (ret_crc != NULL) {
-		init_crc32_table(crc32_table);
-		*ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size);
-	}
-
-	if (fwrite(buf, size, 1, fp) != 1) {
-		rc = -EIO;
-		goto err;
-	}
-
-err:
-	if (buf != NULL)
-		free(buf);
-	return rc;
-}
-
-int
-bootenv_write(FILE* fp, bootenv_t env)
-{
-	return bootenv_write_crc(fp, env, NULL);
-}
-
-int
-bootenv_compare(bootenv_t first, bootenv_t second)
-{
-	int rc;
-	size_t written_first, written_second;
-	char *buf_first, *buf_second;
-
-	if (first == NULL || second == NULL)
-		return -EINVAL;
-
-	buf_first = malloc(BOOTENV_MAXSIZE);
-	if (!buf_first)
-		return -ENOMEM;
-	buf_second = malloc(BOOTENV_MAXSIZE);
-	if (!buf_second) {
-		rc = -ENOMEM;
-		goto err;
-	}
-
-	rc = fill_output_buffer(first, buf_first, BOOTENV_MAXSIZE,
-			&written_first);
-	if (rc < 0)
-		goto err;
-	rc = fill_output_buffer(second, buf_second, BOOTENV_MAXSIZE,
-			&written_second);
-	if (rc < 0)
-		goto err;
-
-	if (written_first != written_second) {
-		rc = 1;
-		goto err;
-	}
-
-	rc = memcmp(buf_first, buf_second, written_first);
-	if (rc != 0) {
-		rc = 2;
-		goto err;
-	}
-
-err:
-	if (buf_first)
-		free(buf_first);
-	if (buf_second)
-		free(buf_second);
-
-	return rc;
-}
-
-int
-bootenv_size(bootenv_t env, size_t *size)
-{
-	int rc = 0;
-	char *buf = NULL;
-
-	if (env == NULL)
-		return -EINVAL;
-
-	buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char));
-	if (buf == NULL)
-		return -ENOMEM;
-
-	rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, size);
-	if (rc != 0)
-		goto err;
-
-err:
-	if (buf != NULL)
-		free(buf);
-	return rc;
-}
-
-int
-bootenv_write_txt(FILE* fp, bootenv_t env)
-{
-	int rc = 0;
-	size_t size, wr, i;
-	const char **keys = NULL;
-	const char *key = NULL;
-	const char *val = NULL;
-
-	if ((fp == NULL) || (env == NULL))
-		return -EINVAL;
-
-	rc = bootenv_get_key_vector(env, &size, 1, &keys);
-	if (rc != 0)
-		goto err;
-
-	for (i = 0; i < size; i++) {
-		key = keys[i];
-		rc = bootenv_get(env, key, &val);
-		if (rc != 0)
-			goto err;
-
-		wr = fprintf(fp, "%s=%s\n", key, val);
-		if (wr != strlen(key) + strlen(val) + 2) {
-			rc = -EIO;
-			goto err;
-		}
-	}
-
-err:
-	if (keys != NULL)
-		free(keys);
-	return rc;
-}
-
-int
-bootenv_valid(bootenv_t env ubi_unused)
-{
-	/* @FIXME No sanity check implemented. */
-	return 0;
-}
-
-int
-bootenv_copy_bootenv(bootenv_t in, bootenv_t *out)
-{
-	int rc = 0;
-	const char *tmp = NULL;
-	const char **keys = NULL;
-	size_t vec_size, i;
-
-	if ((in == NULL) || (out == NULL))
-		return -EINVAL;
-
-	/* purge output var for sure... */
-	rc = bootenv_destroy(out);
-	if (rc != 0)
-		return rc;
-
-	/* create the new map  */
-	rc = bootenv_create(out);
-	if (rc != 0)
-		goto err;
-
-	/* get the key list from the input map */
-	rc = bootenv_get_key_vector(in, &vec_size, 0, &keys);
-	if (rc != 0)
-		goto err;
-
-	if (vec_size != hashmap_size(in->map)) {
-		rc = BOOTENV_ECOPY;
-		goto err;
-	}
-
-	/* make a deep copy of the hashmap */
-	for (i = 0; i < vec_size; i++) {
-		rc = bootenv_get(in, keys[i], &tmp);
-		if (rc != 0)
-			goto err;
-
-		rc = bootenv_set(*out, keys[i], tmp);
-		if (rc != 0)
-			goto err;
-	}
-
-err:
-	if (keys != NULL)
-		free(keys);
-
-	return rc;
-}
-
-/* ------------------------------------------------------------------------- */
-
-
-int
-bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res,
-		 int *warnings, char *err_buf ubi_unused,
-		 size_t err_buf_size ubi_unused)
-{
-	bootenv_list_t l_old = NULL;
-	bootenv_list_t l_new = NULL;
-	const char *pdd_old = NULL;
-	const char *pdd_new = NULL;
-	const char *tmp = NULL;
-	const char **vec_old = NULL;
-	const char **vec_new = NULL;
-	const char **pdd_up_vec = NULL;
-	size_t vec_old_size, vec_new_size, pdd_up_vec_size, i;
-	int rc = 0;
-
-	if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL))
-		return -EINVAL;
-
-	/* get the pdd strings, e.g.:
-	 * pdd_old=a,b,c
-	 * pdd_new=a,c,d,e */
-	rc = bootenv_get(env_old, "pdd", &pdd_old);
-	if (rc != 0)
-		goto err;
-	rc = bootenv_get(env_new, "pdd", &pdd_new);
-	if (rc != 0)
-		goto err;
-
-	/* put it into a list and then convert it to an vector */
-	rc = bootenv_list_create(&l_old);
-	if (rc != 0)
-		goto err;
-	rc  = bootenv_list_create(&l_new);
-	if (rc != 0)
-		goto err;
-
-	rc = bootenv_list_import(l_old, pdd_old);
-	if (rc != 0)
-		goto err;
-
-	rc = bootenv_list_import(l_new, pdd_new);
-	if (rc != 0)
-		goto err;
-
-	rc = bootenv_list_to_vector(l_old, &vec_old_size, &vec_old);
-	if (rc != 0)
-		goto err;
-
-	rc = bootenv_list_to_vector(l_new, &vec_new_size, &vec_new);
-	if (rc != 0)
-		goto err;
-
-	rc = bootenv_copy_bootenv(env_new, env_res);
-	if (rc != 0)
-		goto err;
-
-	/* calculate the update vector between the old and new pdd */
-	pdd_up_vec = hashmap_get_update_key_vector(vec_old, vec_old_size,
-			vec_new, vec_new_size, &pdd_up_vec_size);
-
-	if (pdd_up_vec == NULL) {
-		rc = -ENOMEM;
-		goto err;
-	}
-
-	if (pdd_up_vec_size != 0) {
-		/* need to warn the user about the unset of
-		 * some pdd/bootenv values */
-		*warnings = BOOTENV_WPDD_STRING_DIFFERS;
-
-		/* remove all entries in the new bootenv load */
-		for (i = 0; i < pdd_up_vec_size; i++) {
-			bootenv_unset(*env_res, pdd_up_vec[i]);
-		}
-	}
-
-	/* generate the keep array and copy old pdd values to new bootenv */
-	for (i = 0; i < vec_old_size; i++) {
-		rc = bootenv_get(env_old, vec_old[i], &tmp);
-		if (rc != 0) {
-			rc = BOOTENV_EPDDINVAL;
-			goto err;
-		}
-		rc = bootenv_set(*env_res, vec_old[i], tmp);
-		if (rc != 0) {
-			goto err;
-		}
-	}
-	/* put the old pdd string into the result map */
-	rc = bootenv_set(*env_res, "pdd", pdd_old);
-	if (rc != 0) {
-		goto err;
-	}
-
-
-err:
-	if (vec_old != NULL)
-		free(vec_old);
-	if (vec_new != NULL)
-		free(vec_new);
-	if (pdd_up_vec != NULL)
-		free(pdd_up_vec);
-
-	bootenv_list_destroy(&l_old);
-	bootenv_list_destroy(&l_new);
-	return rc;
-}
-
-
-int
-bootenv_pdd_overwrite(bootenv_t env_old, bootenv_t env_new,
-		      bootenv_t *env_res, int *warnings ubi_unused,
-		      char *err_buf ubi_unused, size_t err_buf_size ubi_unused)
-{
-	if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL))
-		return -EINVAL;
-
-	return bootenv_copy_bootenv(env_new, env_res);
-}
-
-int
-bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res,
-		  int *warnings ubi_unused, char *err_buf, size_t err_buf_size)
-{
-	if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL))
-		return -EINVAL;
-
-	snprintf(err_buf, err_buf_size, "The PDD merge operation is not "
-			"implemented. Contact: <oliloh@de.ibm.com>");
-
-	return BOOTENV_ENOTIMPL;
-}
-
-/* ------------------------------------------------------------------------- */
-
-int
-bootenv_get(bootenv_t env, const char *key, const char **value)
-{
-	if (env == NULL)
-		return -EINVAL;
-
-	*value = hashmap_lookup(env->map, key);
-	if (*value == NULL)
-		return BOOTENV_ENOTFOUND;
-
-	return 0;
-}
-
-int
-bootenv_get_num(bootenv_t env, const char *key, uint32_t *value)
-{
-	char *endptr = NULL;
-	const char *str;
-
-	if (env == NULL)
-		return 0;
-
-	str = hashmap_lookup(env->map, key);
-	if (!str)
-		return -EINVAL;
-
-	*value = strtoul(str, &endptr, 0);
-
-	if (*endptr == '\0') {
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-int
-bootenv_set(bootenv_t env, const char *key, const char *value)
-{
-	if (env == NULL)
-		return -EINVAL;
-
-	return hashmap_add(env->map, key, value);
-}
-
-int
-bootenv_unset(bootenv_t env, const char *key)
-{
-	if (env == NULL)
-		return -EINVAL;
-
-	return hashmap_remove(env->map, key);
-}
-
-int
-bootenv_get_key_vector(bootenv_t env, size_t* size, int sort,
-		       const char ***vector)
-{
-	if ((env == NULL) || (size == NULL))
-		return -EINVAL;
-
-	*vector = hashmap_get_key_vector(env->map, size, sort);
-
-	if (*vector == NULL)
-		return -EINVAL;
-
-	return 0;
-}
-
-int
-bootenv_dump(bootenv_t env)
-{
-	if (env == NULL)
-		return -EINVAL;
-
-	return hashmap_dump(env->map);
-}
-
-int
-bootenv_list_create(bootenv_list_t *list)
-{
-	bootenv_list_t res;
-	res = (bootenv_list_t) calloc(1, sizeof(struct bootenv_list));
-
-	if (res == NULL)
-		return -ENOMEM;
-
-	res->head = hashmap_new();
-
-	if (res->head == NULL) {
-		free(res);
-		return -ENOMEM;
-	}
-
-	*list = res;
-	return 0;
-}
-
-int
-bootenv_list_destroy(bootenv_list_t *list)
-{
-	int rc = 0;
-
-	if (list == NULL)
-		return -EINVAL;
-
-	bootenv_list_t tmp = *list;
-	if (tmp == 0)
-		return 0;
-
-	rc = hashmap_free(tmp->head);
-	if (rc != 0)
-		return rc;
-
-	free(tmp);
-	*list = NULL;
-	return 0;
-}
-
-int
-bootenv_list_import(bootenv_list_t list, const char *str)
-{
-	if (list == NULL)
-		return -EINVAL;
-
-	return build_list_definition(list->head, str);
-}
-
-int
-bootenv_list_export(bootenv_list_t list, char **string)
-{
-	size_t size, i, j, bufsize, tmp, rc = 0;
-	const char **items;
-
-	if (list == NULL)
-		return -EINVAL;
-
-	bufsize = BOOTENV_MAXLINE;
-	char *res = (char*) malloc(bufsize * sizeof(char));
-	if (res == NULL)
-		return -ENOMEM;
-
-	rc = bootenv_list_to_vector(list, &size, &items);
-	if (rc != 0) {
-		goto err;
-	}
-
-	j = 0;
-	for (i = 0; i < size; i++) {
-		tmp = strlen(items[i]);
-		if (j >= bufsize) {
-			bufsize += BOOTENV_MAXLINE;
-			res = (char*) realloc(res, bufsize * sizeof(char));
-			if (res == NULL)  {
-				rc = -ENOMEM;
-				goto err;
-			}
-		}
-		memcpy(res + j, items[i], tmp);
-		j += tmp;
-		if (i < (size - 1)) {
-			res[j] = ',';
-			j++;
-		}
-	}
-	j++;
-	res[j] = '\0';
-	free(items);
-	*string = res;
-	return 0;
-err:
-	free(items);
-	return rc;
-}
-
-int
-bootenv_list_add(bootenv_list_t list, const char *item)
-{
-	if ((list == NULL) || (item == NULL))
-		return -EINVAL;
-
-	return hashmap_add(list->head, item, "");
-}
-
-int
-bootenv_list_remove(bootenv_list_t list, const char *item)
-{
-	if ((list == NULL) || (item == NULL))
-		return -EINVAL;
-
-	return hashmap_remove(list->head, item);
-}
-
-int
-bootenv_list_is_in(bootenv_list_t list, const char *item)
-{
-	if ((list == NULL) || (item == NULL))
-		return -EINVAL;
-
-	return hashmap_lookup(list->head, item) != NULL ? 1 : 0;
-}
-
-int
-bootenv_list_to_vector(bootenv_list_t list, size_t *size, const char ***vector)
-{
-	if ((list == NULL) || (size == NULL))
-		return -EINVAL;
-
-	*vector = hashmap_get_key_vector(list->head, size, 1);
-	if (*vector == NULL)
-		return -ENOMEM;
-
-	return 0;
-}
-
-int
-bootenv_list_to_num_vector(bootenv_list_t list, size_t *size,
-		uint32_t **vector)
-{
-	int rc = 0;
-	size_t i;
-	uint32_t* res = NULL;
-	char *endptr = NULL;
-	const char **a = NULL;
-
-	rc = bootenv_list_to_vector(list, size, &a);
-	if (rc != 0)
-		goto err;
-
-	res = (uint32_t*) malloc (*size * sizeof(uint32_t));
-	if (!res)
-		goto err;
-
-	for (i = 0; i < *size; i++) {
-		res[i] = strtoul(a[i], &endptr, 0);
-		if (*endptr != '\0')
-			goto err;
-	}
-
-	if (a)
-		free(a);
-	*vector = res;
-	return 0;
-
-err:
-	if (a)
-		free(a);
-	if (res)
-		free(res);
-	return rc;
-}
diff --git a/ubi-utils/src/bootenv.h b/ubi-utils/src/bootenv.h
deleted file mode 100644
index 8fecdbf..0000000
--- a/ubi-utils/src/bootenv.h
+++ /dev/null
@@ -1,434 +0,0 @@
-#ifndef __BOOTENV_H__
-#define __BOOTENV_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.
- */
-
-#include <stdio.h> /* FILE */
-#include <stdint.h>
-#include <pfiflash.h>
-
-/* DOXYGEN DOCUMENTATION */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @file bootenv.h
- * @author oliloh@de.ibm.com
- * @version 1.3
- *
- * 1.3 Some renaming
- */
-
-/**
- * @mainpage Usage
- *
- * @section intro Introduction
- * This library provides all functionality to handle with the so-called
- * platform description data (PDD) and the bootparameters defined in
- * U-Boot. It is able to apply the defined PDD operations in PDD update
- * scenarios. For more information about the PDD and bootparameter
- * environment "bootenv" confer the PDD documentation.
- *
- * @section ret Return codes
- * This library defines some return codes which will be delivered classified
- * as warnings or errors. See the "Defines" section for details and numeric
- * values.
- *
- * @section benv Bootenv format description
- * There are two different input formats:
- *	- text files
- *	- binary files
- *
- * @subsection txt Text Files
- * Text files have to be specified like:
- * @verbatim key1=value1,value2,value7\n key2=value55,value1\n key4=value1\n@endverbatim
- *
- * @subsection bin Binary files
- * Binary files have to be specified like:
- * @verbatim<CRC32-bit>key1=value1,value2,value7\0key2=value55,value1\0... @endverbatim
- * You can confer the U-Boot documentation for more details.
- *
- * @section benvlists Bootenv lists format description.
- * Values referenced in the preceeding subsection can be
- * defined like lists:
- * @verbatim value1,value2,value3 @endverbatim
- * There are some situation where a conversion of a comma
- * seperated list can be useful, e.g. to get a list
- * of defined PDD entries.
- */
-
-#define BOOTENV_MAXSIZE (1024 * 100) /* max 100kiB space for bootenv */
-
-/**
- * @def BOOTENV_ECRC
- *	@brief Given binary file is to large.
- * @def BOOTENV_EFMT
- *	@brief Given bootenv section has an invalid format
- * @def BOOTENV_EBADENTRY
- *	@brief Bad entry in the bootenv section.
- * @def BOOTENV_EINVAL
- *	@brief Invalid bootenv defintion.
- * @def BOOTENV_ENOPDD
- *	@brief Given bootenv sectoin has no PDD defintion string (pdd=...).
- * @def BOOTENV_EPDDINVAL
- *	@brief Given bootenv section has an invalid PDD defintion.
- * @def BOOTENV_ENOTIMPL
- *	@brief Functionality not implemented.
- * @def BOOTENV_ECOPY
- *	@brief Bootenv memory copy error
- * @def BOOTENV_ENOTFOUND
- *	@brief Given key has has no value.
- * @def BOOTENV_EMAX
- *	@brief Highest error value.
- */
-#define BOOTENV_ETOOBIG		1
-#define BOOTENV_EFMT		2
-#define BOOTENV_EBADENTRY	3
-#define BOOTENV_EINVAL		4
-#define BOOTENV_ENOPDD		5
-#define BOOTENV_EPDDINVAL	6
-#define BOOTENV_ENOTIMPL	7
-#define BOOTENV_ECOPY		8
-#define BOOTENV_ENOTFOUND	9
-#define BOOTENV_EMAX		10
-
-/**
- * @def BOOTENV_W
- *	@brief A warning which is handled internally as an error
- *	 but can be recovered by manual effort.
- * @def BOOTENV_WPDD_STRING_DIFFERS
- *	@brief The PDD strings of old and new PDD differ and
- *	can cause update problems, because new PDD values
- *	are removed from the bootenv section completely.
- */
-#define BOOTENV_W		     20
-#define BOOTENV_WPDD_STRING_DIFFERS  21
-#define BOOTENV_WMAX 22 /* highest warning value */
-
-
-typedef struct bootenv *bootenv_t;
-	/**< A bootenv library handle. */
-
-typedef struct bootenv_list *bootenv_list_t;
-	/**< A handle for a value list. */
-
-typedef int(*pdd_func_t)(bootenv_t, bootenv_t, bootenv_t*,
-		int*, char*, size_t);
-
-
-/**
- * @brief Get a new handle.
- * @return 0
- * @return or error
- * */
-int bootenv_create(bootenv_t *env);
-
-/**
- * @brief	Cleanup structure.
- * @param env	Bootenv structure which shall be destroyed.
- * @return 0
- * @return or error
- */
-int bootenv_destroy(bootenv_t *env);
-
-/**
- * @brief Copy a bootenv handle.
- * @param in	The input bootenv.
- * @param out	The copied output bootenv. Discards old data.
- * @return 0
- * @return or error
- */
-int bootenv_copy_bootenv(bootenv_t in, bootenv_t *out);
-
-/**
- * @brief Looks for a value inside the bootenv data.
- * @param env Handle to a bootenv structure.
- * @param key The key.
- * @return NULL	 key not found
- * @return !NULL ptr to value
- */
-int bootenv_get(bootenv_t env, const char *key, const char **value);
-
-
-/**
- * @brief Looks for a value inside the bootenv data and converts it to num.
- * @param env Handle to a bootenv structure.
- * @param key The key.
- * @param value A pointer to the resulting numerical value
- * @return NULL	 key not found
- * @return !NULL ptr to value
- */
-int bootenv_get_num(bootenv_t env, const char *key, uint32_t *value);
-
-/**
- * @brief Set a bootenv value by key.
- * @param env   Handle to a bootenv structure.
- * @param key	Key.
- * @param value	Value to set.
- * @return 0
- * @return or error
- */
-int bootenv_set(bootenv_t env, const char *key, const char *value);
-
-/**
- * @brief Remove the given key (and its value) from a bootenv structure.
- * @param env	Handle to a bootenv structure.
- * @param key	Key.
- * @return 0
- * @return or error
- */
-int bootenv_unset(bootenv_t env, const char *key);
-
-
-/**
- * @brief Get a vector of all keys which are currently set
- *        within a bootenv handle.
- * @param env	Handle to a bootenv structure.
- * @param size	The size of the allocated array structure.
- * @param sort	Flag, if set the vector is sorted ascending.
- * @return NULL on error.
- * @return !NULL a pointer to the first element the allocated vector.
- * @warning Free the allocate memory yourself!
- */
-int bootenv_get_key_vector(bootenv_t env, size_t *size, int sort,
-				const char ***vector);
-
-/**
- * @brief Calculate the size in bytes which are necessary to write the
- *        current bootenv section in a *binary file.
- * @param env	bootenv handle.
- * @param size  The size in bytes of the bootenv handle.
- * @return 0
- * @return or ERROR.
- */
-int bootenv_size(bootenv_t env, size_t *size);
-
-/**
- * @brief Read a binary bootenv file.
- * @param fp	File pointer to input stream.
- * @param env	bootenv handle.
- * @param size  maximum data size.
- * @return 0
- * @return or ERROR.
- */
-int bootenv_read(FILE* fp, bootenv_t env, size_t size);
-
-/**
- * @param ret_crc  return value of crc of read data
- */
-int bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t *ret_crc);
-
-/**
- * @brief Read bootenv data from an text/ascii file.
- * @param fp	File pointer to ascii PDD file.
- * @param env	bootenv handle
- * @return 0
- * @return or ERROR.
- */
-int bootenv_read_txt(FILE* fp, bootenv_t env);
-
-/**
- * @brief Write a bootenv structure to the given location (binary).
- * @param fp	Filepointer to binary file.
- * @param env	Bootenv structure which shall be written.
- * @return 0
- * @return or error
- */
-int bootenv_write(FILE* fp, bootenv_t env);
-
-/**
- * @param ret_crc  return value of crc of read data
- */
-int bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc);
-
-/**
- * @brief Write a bootenv structure to the given location (text).
- * @param fp	Filepointer to text file.
- * @param env	Bootenv structure which shall be written.
- * @return 0
- * @return or error
- */
-int bootenv_write_txt(FILE* fp, bootenv_t env);
-
-/**
- * @brief Compare bootenvs using memcmp().
- * @param first	First bootenv.
- * @param second	Second bootenv.
- * @return 0 if bootenvs are equal
- * @return < 0 if error
- * @return > 0 if unequal
- */
-int bootenv_compare(bootenv_t first, bootenv_t second);
-
-/**
- * @brief Prototype for a PDD handling funtion
- */
-
-/**
- * @brief The PDD keep operation.
- * @param env_old The old bootenv structure.
- * @param env_new The new bootenv structure.
- * @param env_res The result of PDD keep.
- * @param warnings A flag which marks any warnings.
- * @return 0
- * @return or error
- * @note For a complete documentation about the algorithm confer the
- *       PDD documentation.
- */
-int bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new,
-		bootenv_t *env_res, int *warnings,
-		char *err_buf, size_t err_buf_size);
-
-
-/**
- * @brief The PDD merge operation.
- * @param env_old The old bootenv structure.
- * @param env_new The new bootenv structure.
- * @param env_res The result of merge-pdd.
- * @param warnings A flag which marks any warnings.
- * @return 0
- * @return or error
- * @note For a complete documentation about the algorithm confer the
- *       PDD documentation.
- */
-int bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new,
-		bootenv_t *env_res, int *warnings,
-		char *err_buf, size_t err_buf_size);
-
-/**
- * @brief The PDD overwrite operation.
- * @param env_old The old bootenv structure.
- * @param env_new The new bootenv structure.
- * @param env_res The result of overwrite-pdd.
- * @param warnings A flag which marks any warnings.
- * @return 0
- * @return or error
- * @note For a complete documentation about the algorithm confer the
- *       PDD documentation.
- */
-int bootenv_pdd_overwrite(bootenv_t env_new,
-		bootenv_t env_old, bootenv_t *env_res, int *warnings,
-		char *err_buf, size_t err_buf_size);
-
-/**
- * @brief Dump a bootenv structure to stdout. (Debug)
- * @param env	Handle to a bootenv structure.
- * @return 0
- * @return or error
- */
-int bootenv_dump(bootenv_t env);
-
-/**
- * @brief Validate a bootenv structure.
- * @param env Handle to a bootenv structure.
- * @return 0
- * @return or error
- */
-int bootenv_valid(bootenv_t env);
-
-/**
- * @brief Create a new bootenv list structure.
- * @return NULL on error
- * @return or a new list handle.
- * @note This structure is used to store values in a list.
- *       A useful addition when handling PDD strings.
- */
-int bootenv_list_create(bootenv_list_t *list);
-
-/**
- * @brief Destroy a bootenv list structure
- * @param list	Handle to a bootenv list structure.
- * @return 0
- * @return or error
- */
-int bootenv_list_destroy(bootenv_list_t *list);
-
-/**
- * @brief Import a list from a comma seperated string
- * @param list	Handle to a bootenv list structure.
- * @param str		Comma seperated string list.
- * @return 0
- * @return or error
- */
-int bootenv_list_import(bootenv_list_t list, const char *str);
-
-/**
- * @brief Export a list to a string of comma seperated values.
- * @param list	Handle to a bootenv list structure.
- * @return NULL one error
- * @return or pointer to a newly allocated string.
- * @warning Free the allocated memory by yourself!
- */
-int bootenv_list_export(bootenv_list_t list, char **string);
-
-/**
- * @brief Add an item to the list.
- * @param list	A handle of a list structure.
- * @param item	An item.
- * @return 0
- * @return or error
- */
-int bootenv_list_add(bootenv_list_t list, const char *item);
-
-/**
- * @brief Remove an item from the list.
- * @param list	A handle of a list structure.
- * @param item	An item.
- * @return 0
- * @return or error
- */
-int bootenv_list_remove(bootenv_list_t list, const char *item);
-
-/**
- * @brief Check if a given item is in a given list.
- * @param list	A handle of a list structure.
- * @param item	An item.
- * @return 1 Item is in list.
- * @return 0 Item is not in list.
- */
-int bootenv_list_is_in(bootenv_list_t list, const char *item);
-
-
-/**
- * @brief Convert a list into a vector of all values inside the list.
- * @param list	Handle to a bootenv structure.
- * @param size	The size of the allocated vector structure.
- * @return 0
- * @return or error
- * @warning Free the allocate memory yourself!
- */
-int bootenv_list_to_vector(bootenv_list_t list, size_t *size,
-			   const char ***vector);
-
-/**
- * @brief Convert a list into a vector of all values inside the list.
- * @param list	Handle to a bootenv structure.
- * @param size	The size of the allocated vector structure.
- * @return 0
- * @return or error
- * @warning Free the allocate memory yourself!
- */
-int bootenv_list_to_num_vector(bootenv_list_t list, size_t *size,
-					uint32_t **vector);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /*__BOOTENV_H__ */
diff --git a/ubi-utils/src/common.c b/ubi-utils/src/common.c
new file mode 100644
index 0000000..bcb775c
--- /dev/null
+++ b/ubi-utils/src/common.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2007, 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.
+ */
+
+/*
+ * This file contains various common stuff used by UBI utilities.
+ *
+ * Authors: Artem Bityutskiy
+ *          Adrian Hunter
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/**
+ * get_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.
+ */
+static int 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;
+
+	/* Handle deprecated stuff */
+	if (!strcmp(str, "KB") || !strcmp(str, "Kib") || !strcmp(str, "kib") ||
+	    !strcmp(str, "kiB")) {
+		fprintf(stderr, "Warning: use \"KiB\" instead of \"%s\" to "
+			"specify Kilobytes - support will be removed\n", str);
+		return 1024;
+	}
+	if (!strcmp(str, "MB") || !strcmp(str, "Mib") || !strcmp(str, "mb")) {
+		fprintf(stderr, "Warning: use \"MiB\" instead of \"%s\", "
+			"this support will be removed\n", str);
+		return 1024*1024;
+	}
+	if (!strcmp(str, "GB") || !strcmp(str, "Gib") || !strcmp(str, "gb")) {
+		fprintf(stderr, "Warning: use \"GiB\" instead of \"%s\", "
+			"this support will be removed\n", str);
+		return 1024*1024*1024;
+	}
+
+	return -1;
+}
+
+/**
+ * ubiutils_get_bytes - convert a string containing amount of bytes into an
+ * integer
+ * @str: string to convert
+ *
+ * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
+ * size specifiers. Returns positive amount of bytes in case of success and %-1
+ * in case of failure.
+ */
+long long ubiutils_get_bytes(const char *str)
+{
+	char *endp;
+	long long bytes = strtoull(str, &endp, 0);
+
+	if (endp == str || bytes < 0) {
+		fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str);
+		return -1;
+	}
+
+	if (*endp != '\0') {
+		int mult = get_multiplier(endp);
+
+		if (mult == -1) {
+			fprintf(stderr, "bad size specifier: \"%s\" - "
+			        "should be 'KiB', 'MiB' or 'GiB'\n", endp);
+			return -1;
+		}
+		bytes *= mult;
+	}
+
+	return bytes;
+}
+
+/**
+ * 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 && bytes != 0)
+		printf("%s%.1f KiB", p, (double)bytes / 1024);
+	else
+		return;
+
+	if (bracket)
+		printf(")");
+}
+
+/**
+ * ubiutils_print_text - print text and fold it.
+ * @stream: file stream to print to
+ * @text: text to print
+ * @width: maximum allowed text width
+ *
+ * Print text and fold it so that each line would not have more then @width
+ * characters.
+ */
+void ubiutils_print_text(FILE *stream, const char *text, int width)
+{
+	int pos, bpos = 0;
+	const char *p;
+	char line[1024];
+
+	if (width > 1023) {
+		fprintf(stream, "%s\n", text);
+		return;
+	}
+	p = text;
+	pos = 0;
+	while (p[pos]) {
+		while (!isspace(p[pos])) {
+			line[pos] = p[pos];
+			if (!p[pos])
+				break;
+			++pos;
+			if (pos == width) {
+				line[pos] = '\0';
+				fprintf(stream, "%s\n", line);
+				p += pos;
+				pos = 0;
+			}
+		}
+		while (pos < width) {
+			line[pos] = p[pos];
+			if (!p[pos]) {
+				bpos = pos;
+				break;
+			}
+			if (isspace(p[pos]))
+				bpos = pos;
+			++pos;
+		}
+		line[bpos] = '\0';
+		fprintf(stream, "%s\n", line);
+		p += bpos;
+		pos = 0;
+		while (p[pos] && isspace(p[pos]))
+			++p;
+	}
+}
diff --git a/ubi-utils/src/common.h b/ubi-utils/src/common.h
new file mode 100644
index 0000000..56fa020
--- /dev/null
+++ b/ubi-utils/src/common.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) Artem Bityutskiy, 2007, 2008
+ *
+ * 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__
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIN(a ,b) ((a) < (b) ? (a) : (b))
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+/* Verbose messages */
+#define verbose(verbose, fmt, ...) do {                            \
+	if (verbose)                                               \
+		printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \
+} while(0)
+
+/* Normal messages */
+#define normsg(fmt, ...) do {                              \
+	printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \
+} while(0)
+#define normsg_cont(fmt, ...) do {                    \
+	printf(PROGRAM_NAME ": " fmt, ##__VA_ARGS__); \
+} while(0)
+#define normsg_cont(fmt, ...) do {                         \
+	printf(PROGRAM_NAME ": " fmt, ##__VA_ARGS__);      \
+} while(0)
+
+/* Error messages */
+#define errmsg(fmt, ...)  ({                                                \
+	fprintf(stderr, PROGRAM_NAME ": error!: " fmt "\n", ##__VA_ARGS__); \
+	-1;                                                                 \
+})
+
+/* System error messages */
+#define sys_errmsg(fmt, ...)  ({                                            \
+	int _err = errno;                                                   \
+	size_t _i;                                                           \
+	fprintf(stderr, PROGRAM_NAME ": error!: " fmt "\n", ##__VA_ARGS__); \
+	for (_i = 0; _i < sizeof(PROGRAM_NAME) + 1; _i++)                   \
+		fprintf(stderr, " ");                                       \
+	fprintf(stderr, "error %d (%s)\n", _err, strerror(_err));           \
+	-1;                                                                 \
+})
+
+/* Warnings */
+#define warnmsg(fmt, ...) do {                                                \
+	fprintf(stderr, PROGRAM_NAME ": warning!: " fmt "\n", ##__VA_ARGS__); \
+} while(0)
+
+static inline int is_power_of_2(unsigned long long n)
+{
+	        return (n != 0 && ((n & (n - 1)) == 0));
+}
+
+long long ubiutils_get_bytes(const char *str);
+void ubiutils_print_bytes(long long bytes, int bracket);
+void ubiutils_print_text(FILE *stream, const char *txt, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__UBI_UTILS_COMMON_H__ */
diff --git a/ubi-utils/src/config.h b/ubi-utils/src/config.h
deleted file mode 100644
index 55e60f3..0000000
--- a/ubi-utils/src/config.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __CONFIG_H__
-#define __CONFIG_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: Frank Haverkamp
- */
-
-#define PACKAGE_BUGREPORT						\
-	"haver@vnet.ibm.com, dedekind@linutronix.de, or tglx@linutronix.de"
-
-#define ubi_unused __attribute__((unused))
-
-#endif
diff --git a/ubi-utils/src/crc32.c b/ubi-utils/src/crc32.c
index 666e217..6b1e50c 100644
--- a/ubi-utils/src/crc32.c
+++ b/ubi-utils/src/crc32.c
@@ -1,83 +1,95 @@
 /*
- * Copyright (c) International Business Machines Corp., 2006
+ *  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
+ *  code or tables extracted from it, as desired without restriction.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ *  First, the polynomial itself and its table of feedback terms.  The
+ *  polynomial is
+ *  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
+ *  Note that we take it "backwards" and put the highest-order term in
+ *  the lowest-order bit.  The X^32 term is "implied"; the LSB is the
+ *  X^31 term, etc.  The X^0 term (usually shown as "+1") results in
+ *  the MSB being 1
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  Note that the usual hardware shift register implementation, which
+ *  is what we're using (we're merely optimizing it by doing eight-bit
+ *  chunks at a time) shifts bits into the lowest-order term.  In our
+ *  implementation, that means shifting towards the right.  Why do we
+ *  do it this way?  Because the calculated CRC must be transmitted in
+ *  order from highest-order term to lowest-order term.  UARTs transmit
+ *  characters in order from LSB to MSB.  By storing the CRC this way
+ *  we hand it to the UART in the order low-byte to high-byte; the UART
+ *  sends each low-bit to hight-bit; and the result is transmission bit
+ *  by bit from highest- to lowest-order term without requiring any bit
+ *  shuffling on our part.  Reception works similarly
  *
- * Author: Thomas Gleixner
- */
-
-/*
- * CRC32 functions
+ *  The feedback terms table consists of 256, 32-bit entries.  Notes
  *
- * Can be compiled as seperate object, but is included into the ipl source
- * so gcc can inline the functions. We optimize for size so the omission of
- * the function frame is helpful.
+ *      The table can be generated at runtime if desired; code to do so
+ *      is shown later.  It might not be obvious, but the feedback
+ *      terms simply represent the results of eight shift/xor opera
+ *      tions for all combinations of data and CRC register values
  *
+ *      The values must be right-shifted by eight bits by the "updcrc
+ *      logic; the shift must be unsigned (bring in zeroes).  On some
+ *      hardware you could probably optimize the shift in assembler by
+ *      using byte-swap instructions
+ *      polynomial $edb88320
  */
 
 #include <stdint.h>
-#include <crc32.h>
-
-/* CRC polynomial */
-#define CRC_POLY	0xEDB88320
-
-/**
- * init_crc32_table - Initialize crc table
- *
- * @table:	pointer to the CRC table which must be initialized
- *
- * Create CRC32 table for given polynomial. The table is created with
- * the lowest order term in the highest order bit. So the x^32 term
- * has to implied in the crc calculation function.
- */
-void init_crc32_table(uint32_t *table)
-{
-	uint32_t crc;
-	int i, j;
-
-	for (i = 0; i < 256; i++) {
-		crc = i;
-		for (j = 8; j > 0; j--) {
-			if (crc & 1)
-				crc = (crc >> 1) ^ CRC_POLY;
-			else
-				crc >>= 1;
-		}
-		table[i] = crc;
-	}
-}
-
-/**
- * clc_crc32 - Calculate CRC32 over a buffer
- *
- * @table:	pointer to the CRC table
- * @crc:	initial crc value
- * @buf:	pointer to the buffer
- * @len:	number of bytes to calc
- *
- * Returns the updated crc value.
- *
- * The algorithm resembles a hardware shift register, but calculates 8
- * bit at once.
- */
-uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf,
-		   int len)
-{
-	const unsigned char *p = buf;
 
-	while(--len >= 0)
-		crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-	return crc;
-}
+const uint32_t crc32_table[256] = {
+	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+	0x2d02ef8dL
+};
diff --git a/ubi-utils/src/crc32.h b/ubi-utils/src/crc32.h
index 31362b0..ee3145b 100644
--- a/ubi-utils/src/crc32.h
+++ b/ubi-utils/src/crc32.h
@@ -1,36 +1,19 @@
-#ifndef __CRC32_H__
-#define __CRC32_H__
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+#ifndef CRC32_H
+#define CRC32_H
 
-/*
- * Author: Thomas Gleixner
- *
- * CRC32 functions
- *
- * Can be compiled as seperate object, but is included into the ipl source
- * so gcc can inline the functions. We optimize for size so the omission of
- * the function frame is helpful.
- *
- */
 #include <stdint.h>
 
-void init_crc32_table(uint32_t *table);
-uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len);
+extern const uint32_t crc32_table[256];
 
-#endif /* __CRC32_H__ */
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+	static inline uint32_t
+crc32(uint32_t val, const void *ss, int len)
+{
+	const unsigned char *s = ss;
+	while (--len >= 0)
+		val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
+	return val;
+}
+
+#endif
diff --git a/ubi-utils/src/dictionary.c b/ubi-utils/src/dictionary.c
new file mode 100644
index 0000000..b7c9ebf
--- /dev/null
+++ b/ubi-utils/src/dictionary.c
@@ -0,0 +1,405 @@
+/*-------------------------------------------------------------------------*/
+/**
+   @file	dictionary.c
+   @author	N. Devillard
+   @date	Sep 2007
+   @version	$Revision: 1.27 $
+   @brief	Implements a dictionary for string variables.
+
+   This module implements a simple dictionary object, i.e. a list
+   of string/string associations. This object is useful to store e.g.
+   informations retrieved from a configuration file (ini files).
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+	$Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $
+	$Revision: 1.27 $
+*/
+/*---------------------------------------------------------------------------
+   								Includes
+ ---------------------------------------------------------------------------*/
+#include "dictionary.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/** Maximum value size for integers and doubles. */
+#define MAXVALSZ	1024
+
+/** Minimal allocated number of entries in a dictionary */
+#define DICTMINSZ	128
+
+/** Invalid key token */
+#define DICT_INVALID_KEY    ((char*)-1)
+
+/*---------------------------------------------------------------------------
+  							Private functions
+ ---------------------------------------------------------------------------*/
+
+/* Doubles the allocated size associated to a pointer */
+/* 'size' is the current allocated size. */
+static void * mem_double(void * ptr, int size)
+{
+    void * newptr ;
+ 
+    newptr = calloc(2*size, 1);
+    if (newptr==NULL) {
+        return NULL ;
+    }
+    memcpy(newptr, ptr, size);
+    free(ptr);
+    return newptr ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Duplicate a string
+  @param    s String to duplicate
+  @return   Pointer to a newly allocated string, to be freed with free()
+
+  This is a replacement for strdup(). This implementation is provided
+  for systems that do not have it.
+ */
+/*--------------------------------------------------------------------------*/
+static char * xstrdup(char * s)
+{
+    char * t ;
+    if (!s)
+        return NULL ;
+    t = malloc(strlen(s)+1) ;
+    if (t) {
+        strcpy(t,s);
+    }
+    return t ;
+}
+
+/*---------------------------------------------------------------------------
+  							Function codes
+ ---------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Compute the hash key for a string.
+  @param	key		Character string to use for key.
+  @return	1 unsigned int on at least 32 bits.
+
+  This hash function has been taken from an Article in Dr Dobbs Journal.
+  This is normally a collision-free function, distributing keys evenly.
+  The key is stored anyway in the struct so that collision can be avoided
+  by comparing the key itself in last resort.
+ */
+/*--------------------------------------------------------------------------*/
+unsigned dictionary_hash(char * key)
+{
+	int			len ;
+	unsigned	hash ;
+	int			i ;
+
+	len = strlen(key);
+	for (hash=0, i=0 ; i<len ; i++) {
+		hash += (unsigned)key[i] ;
+		hash += (hash<<10);
+		hash ^= (hash>>6) ;
+	}
+	hash += (hash <<3);
+	hash ^= (hash >>11);
+	hash += (hash <<15);
+	return hash ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Create a new dictionary object.
+  @param	size	Optional initial size of the dictionary.
+  @return	1 newly allocated dictionary objet.
+
+  This function allocates a new dictionary object of given size and returns
+  it. If you do not know in advance (roughly) the number of entries in the
+  dictionary, give size=0.
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * dictionary_new(int size)
+{
+	dictionary	*	d ;
+
+	/* If no size was specified, allocate space for DICTMINSZ */
+	if (size<DICTMINSZ) size=DICTMINSZ ;
+
+	if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
+		return NULL;
+	}
+	d->size = size ;
+	d->val  = (char **)calloc(size, sizeof(char*));
+	d->key  = (char **)calloc(size, sizeof(char*));
+	d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
+	return d ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Delete a dictionary object
+  @param	d	dictionary object to deallocate.
+  @return	void
+
+  Deallocate a dictionary object and all memory associated to it.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_del(dictionary * d)
+{
+	int		i ;
+
+	if (d==NULL) return ;
+	for (i=0 ; i<d->size ; i++) {
+		if (d->key[i]!=NULL)
+			free(d->key[i]);
+		if (d->val[i]!=NULL)
+			free(d->val[i]);
+	}
+	free(d->val);
+	free(d->key);
+	free(d->hash);
+	free(d);
+	return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Get a value from a dictionary.
+  @param	d		dictionary object to search.
+  @param	key		Key to look for in the dictionary.
+  @param    def     Default value to return if key not found.
+  @return	1 pointer to internally allocated character string.
+
+  This function locates a key in a dictionary and returns a pointer to its
+  value, or the passed 'def' pointer if no such key can be found in
+  dictionary. The returned character pointer points to data internal to the
+  dictionary object, you should not try to free it or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * dictionary_get(dictionary * d, char * key, char * def)
+{
+	unsigned	hash ;
+	int			i ;
+
+	hash = dictionary_hash(key);
+	for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        /* Compare hash */
+		if (hash==d->hash[i]) {
+            /* Compare string, to avoid hash collisions */
+            if (!strcmp(key, d->key[i])) {
+				return d->val[i] ;
+			}
+		}
+	}
+	return def ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Set a value in a dictionary.
+  @param    d       dictionary object to modify.
+  @param    key     Key to modify or add.
+  @param    val     Value to add.
+  @return   int     0 if Ok, anything else otherwise
+
+  If the given key is found in the dictionary, the associated value is
+  replaced by the provided one. If the key cannot be found in the
+  dictionary, it is added to it.
+
+  It is Ok to provide a NULL value for val, but NULL values for the dictionary
+  or the key are considered as errors: the function will return immediately
+  in such a case.
+
+  Notice that if you dictionary_set a variable to NULL, a call to
+  dictionary_get will return a NULL value: the variable will be found, and
+  its value (NULL) is returned. In other words, setting the variable
+  content to NULL is equivalent to deleting the variable from the
+  dictionary. It is not possible (in this implementation) to have a key in
+  the dictionary without value.
+
+  This function returns non-zero in case of failure.
+ */
+/*--------------------------------------------------------------------------*/
+int dictionary_set(dictionary * d, char * key, char * val)
+{
+	int			i ;
+	unsigned	hash ;
+
+	if (d==NULL || key==NULL) return -1 ;
+	
+	/* Compute hash for this key */
+	hash = dictionary_hash(key) ;
+	/* Find if value is already in dictionary */
+	if (d->n>0) {
+		for (i=0 ; i<d->size ; i++) {
+            if (d->key[i]==NULL)
+                continue ;
+			if (hash==d->hash[i]) { /* Same hash value */
+				if (!strcmp(key, d->key[i])) {	 /* Same key */
+					/* Found a value: modify and return */
+					if (d->val[i]!=NULL)
+						free(d->val[i]);
+                    d->val[i] = val ? xstrdup(val) : NULL ;
+                    /* Value has been modified: return */
+					return 0 ;
+				}
+			}
+		}
+	}
+	/* Add a new value */
+	/* See if dictionary needs to grow */
+	if (d->n==d->size) {
+
+		/* Reached maximum size: reallocate dictionary */
+		d->val  = (char **)mem_double(d->val,  d->size * sizeof(char*)) ;
+		d->key  = (char **)mem_double(d->key,  d->size * sizeof(char*)) ;
+		d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
+        if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
+            /* Cannot grow dictionary */
+            return -1 ;
+        }
+		/* Double size */
+		d->size *= 2 ;
+	}
+
+    /* Insert key in the first empty slot */
+    for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL) {
+            /* Add key here */
+            break ;
+        }
+    }
+	/* Copy key */
+	d->key[i]  = xstrdup(key);
+    d->val[i]  = val ? xstrdup(val) : NULL ;
+	d->hash[i] = hash;
+	d->n ++ ;
+	return 0 ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Delete a key in a dictionary
+  @param	d		dictionary object to modify.
+  @param	key		Key to remove.
+  @return   void
+
+  This function deletes a key in a dictionary. Nothing is done if the
+  key cannot be found.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_unset(dictionary * d, char * key)
+{
+	unsigned	hash ;
+	int			i ;
+
+	if (key == NULL) {
+		return;
+	}
+
+	hash = dictionary_hash(key);
+	for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        /* Compare hash */
+		if (hash==d->hash[i]) {
+            /* Compare string, to avoid hash collisions */
+            if (!strcmp(key, d->key[i])) {
+                /* Found key */
+                break ;
+			}
+		}
+	}
+    if (i>=d->size)
+        /* Key not found */
+        return ;
+
+    free(d->key[i]);
+    d->key[i] = NULL ;
+    if (d->val[i]!=NULL) {
+        free(d->val[i]);
+        d->val[i] = NULL ;
+    }
+    d->hash[i] = 0 ;
+    d->n -- ;
+    return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Dump a dictionary to an opened file pointer.
+  @param	d	Dictionary to dump
+  @param	f	Opened file pointer.
+  @return	void
+
+  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
+  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
+  output file pointers.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_dump(dictionary * d, FILE * out)
+{
+	int		i ;
+
+	if (d==NULL || out==NULL) return ;
+	if (d->n<1) {
+		fprintf(out, "empty dictionary\n");
+		return ;
+	}
+	for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]) {
+            fprintf(out, "%20s\t[%s]\n",
+                    d->key[i],
+                    d->val[i] ? d->val[i] : "UNDEF");
+        }
+	}
+	return ;
+}
+
+
+/* Test code */
+#ifdef TESTDIC
+#define NVALS 20000
+int main(int argc, char *argv[])
+{
+	dictionary	*	d ;
+	char	*	val ;
+	int			i ;
+	char		cval[90] ;
+
+	/* Allocate dictionary */
+	printf("allocating...\n");
+	d = dictionary_new(0);
+	
+	/* Set values in dictionary */
+	printf("setting %d values...\n", NVALS);
+	for (i=0 ; i<NVALS ; i++) {
+		sprintf(cval, "%04d", i);
+		dictionary_set(d, cval, "salut");
+	}
+	printf("getting %d values...\n", NVALS);
+	for (i=0 ; i<NVALS ; i++) {
+		sprintf(cval, "%04d", i);
+		val = dictionary_get(d, cval, DICT_INVALID_KEY);
+		if (val==DICT_INVALID_KEY) {
+			printf("cannot get value for key [%s]\n", cval);
+		}
+	}
+    printf("unsetting %d values...\n", NVALS);
+	for (i=0 ; i<NVALS ; i++) {
+		sprintf(cval, "%04d", i);
+		dictionary_unset(d, cval);
+	}
+    if (d->n != 0) {
+        printf("error deleting values\n");
+    }
+	printf("deallocating...\n");
+	dictionary_del(d);
+	return 0 ;
+}
+#endif
+/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/ubi-utils/src/dictionary.h b/ubi-utils/src/dictionary.h
new file mode 100644
index 0000000..c7d1790
--- /dev/null
+++ b/ubi-utils/src/dictionary.h
@@ -0,0 +1,174 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+   @file    dictionary.h
+   @author  N. Devillard
+   @date    Sep 2007
+   @version $Revision: 1.12 $
+   @brief   Implements a dictionary for string variables.
+
+   This module implements a simple dictionary object, i.e. a list
+   of string/string associations. This object is useful to store e.g.
+   informations retrieved from a configuration file (ini files).
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+	$Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $
+	$Author: ndevilla $
+	$Date: 2007-11-23 21:37:00 $
+	$Revision: 1.12 $
+*/
+
+#ifndef _DICTIONARY_H_
+#define _DICTIONARY_H_
+
+/*---------------------------------------------------------------------------
+   								Includes
+ ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*---------------------------------------------------------------------------
+   								New types
+ ---------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Dictionary object
+
+  This object contains a list of string/string associations. Each
+  association is identified by a unique string key. Looking up values
+  in the dictionary is speeded up by the use of a (hopefully collision-free)
+  hash function.
+ */
+/*-------------------------------------------------------------------------*/
+typedef struct _dictionary_ {
+	int				n ;		/** Number of entries in dictionary */
+	int				size ;	/** Storage size */
+	char 		**	val ;	/** List of string values */
+	char 		**  key ;	/** List of string keys */
+	unsigned	 *	hash ;	/** List of hash values for keys */
+} dictionary ;
+
+
+/*---------------------------------------------------------------------------
+  							Function prototypes
+ ---------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Compute the hash key for a string.
+  @param    key     Character string to use for key.
+  @return   1 unsigned int on at least 32 bits.
+
+  This hash function has been taken from an Article in Dr Dobbs Journal.
+  This is normally a collision-free function, distributing keys evenly.
+  The key is stored anyway in the struct so that collision can be avoided
+  by comparing the key itself in last resort.
+ */
+/*--------------------------------------------------------------------------*/
+unsigned dictionary_hash(char * key);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Create a new dictionary object.
+  @param    size    Optional initial size of the dictionary.
+  @return   1 newly allocated dictionary objet.
+
+  This function allocates a new dictionary object of given size and returns
+  it. If you do not know in advance (roughly) the number of entries in the
+  dictionary, give size=0.
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * dictionary_new(int size);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Delete a dictionary object
+  @param    d   dictionary object to deallocate.
+  @return   void
+
+  Deallocate a dictionary object and all memory associated to it.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_del(dictionary * vd);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get a value from a dictionary.
+  @param    d       dictionary object to search.
+  @param    key     Key to look for in the dictionary.
+  @param    def     Default value to return if key not found.
+  @return   1 pointer to internally allocated character string.
+
+  This function locates a key in a dictionary and returns a pointer to its
+  value, or the passed 'def' pointer if no such key can be found in
+  dictionary. The returned character pointer points to data internal to the
+  dictionary object, you should not try to free it or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * dictionary_get(dictionary * d, char * key, char * def);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Set a value in a dictionary.
+  @param    d       dictionary object to modify.
+  @param    key     Key to modify or add.
+  @param    val     Value to add.
+  @return   int     0 if Ok, anything else otherwise
+
+  If the given key is found in the dictionary, the associated value is
+  replaced by the provided one. If the key cannot be found in the
+  dictionary, it is added to it.
+
+  It is Ok to provide a NULL value for val, but NULL values for the dictionary
+  or the key are considered as errors: the function will return immediately
+  in such a case.
+
+  Notice that if you dictionary_set a variable to NULL, a call to
+  dictionary_get will return a NULL value: the variable will be found, and
+  its value (NULL) is returned. In other words, setting the variable
+  content to NULL is equivalent to deleting the variable from the
+  dictionary. It is not possible (in this implementation) to have a key in
+  the dictionary without value.
+
+  This function returns non-zero in case of failure.
+ */
+/*--------------------------------------------------------------------------*/
+int dictionary_set(dictionary * vd, char * key, char * val);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Delete a key in a dictionary
+  @param    d       dictionary object to modify.
+  @param    key     Key to remove.
+  @return   void
+
+  This function deletes a key in a dictionary. Nothing is done if the
+  key cannot be found.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_unset(dictionary * d, char * key);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Dump a dictionary to an opened file pointer.
+  @param    d   Dictionary to dump
+  @param    f   Opened file pointer.
+  @return   void
+
+  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
+  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
+  output file pointers.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_dump(dictionary * d, FILE * out);
+
+#endif
diff --git a/ubi-utils/src/eb_chain.c b/ubi-utils/src/eb_chain.c
deleted file mode 100644
index da5c2e3..0000000
--- a/ubi-utils/src/eb_chain.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006, 2007
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Author:  Drake Dowsett, dowsett@de.ibm.com
- * Contact: Andreas Arnez, arnez@de.ibm.com
- */
-
-/* see eb_chain.h */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <mtd_swab.h>
-#include "unubi_analyze.h"
-#include "crc32.h"
-
-#define COPY(dst, src)							\
-	do {								\
-		dst = malloc(sizeof(*dst));				\
-		if (dst == NULL)					\
-			return -ENOMEM;					\
-		memcpy(dst, src, sizeof(*dst));				\
-	} while (0)
-
-
-/**
- * inserts an eb_info into the chain starting at head, then searching
- * linearly for the correct position;
- * new should contain valid vid and ec headers and the data_crc should
- * already have been checked before insertion, otherwise the chain
- * could be have un an undesired manner;
- * returns -ENOMEM if alloc fails, otherwise SHOULD always return 0,
- * if not, the code reached the last line and returned -EAGAIN,
- * meaning there is a bug or a case not being handled here;
- **/
-int
-eb_chain_insert(struct eb_info **head, struct eb_info *new)
-{
-	uint32_t vol, num, ver;
-	uint32_t new_vol, new_num, new_ver;
-	struct eb_info *prev, *cur, *hist, *ins;
-	struct eb_info **prev_ptr;
-
-	if ((head == NULL) || (new == NULL))
-		return 0;
-
-	if (*head == NULL) {
-		COPY(*head, new);
-		(*head)->next = NULL;
-		return 0;
-	}
-
-	new_vol = be32_to_cpu(new->vid.vol_id);
-	new_num = be32_to_cpu(new->vid.lnum);
-	new_ver = be32_to_cpu(new->vid.leb_ver);
-
-	/** TRAVERSE HORIZONTALY **/
-
-	cur = *head;
-	prev = NULL;
-
-	/* traverse until vol_id/lnum align */
-	vol = be32_to_cpu(cur->vid.vol_id);
-	num = be32_to_cpu(cur->vid.lnum);
-	while ((new_vol > vol) || ((new_vol == vol) && (new_num > num))) {
-		/* insert new at end of chain */
-		if (cur->next == NULL) {
-			COPY(ins, new);
-			ins->next = NULL;
-			cur->next = ins;
-			return 0;
-		}
-
-		prev = cur;
-		cur = cur->next;
-		vol = be32_to_cpu(cur->vid.vol_id);
-		num = be32_to_cpu(cur->vid.lnum);
-	}
-
-	if (prev == NULL)
-		prev_ptr = head;
-	else
-		prev_ptr = &(prev->next);
-
-	/* insert new into the middle of chain */
-	if ((new_vol != vol) || (new_num != num)) {
-		COPY(ins, new);
-		ins->next = cur;
-		*prev_ptr = ins;
-		return 0;
-	}
-
-	/** TRAVERSE VERTICALY **/
-
-	hist = cur;
-	prev = NULL;
-
-	/* traverse until versions align */
-	ver = be32_to_cpu(cur->vid.leb_ver);
-	while (new_ver < ver) {
-		/* insert new at bottom of history */
-		if (hist->older == NULL) {
-			COPY(ins, new);
-			ins->next = NULL;
-			ins->older = NULL;
-			hist->older = ins;
-			return 0;
-		}
-
-		prev = hist;
-		hist = hist->older;
-		ver = be32_to_cpu(hist->vid.leb_ver);
-	}
-
-	if (prev == NULL) {
-		/* replace active version */
-		COPY(ins, new);
-		ins->next = hist->next;
-		*prev_ptr = ins;
-
-		/* place cur in vertical histroy */
-		ins->older = hist;
-		hist->next = NULL;
-		return 0;
-	}
-
-	/* insert between versions, beneath active version */
-	COPY(ins, new);
-	ins->next = NULL;
-	ins->older = prev->older;
-	prev->older = ins;
-	return 0;
-}
-
-
-/**
- * sets the pointer at pos to the position of the first entry in the chain
- * with of vol_id and, if given, with the same lnum as *lnum;
- * if there is no entry in the chain, then *pos is NULL on return;
- * always returns 0;
- **/
-int
-eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum,
-		  struct eb_info **pos)
-{
-	uint32_t vol, num;
-	struct eb_info *cur;
-
-	if ((head == NULL) || (*head == NULL) || (pos == NULL))
-		return 0;
-
-	*pos = NULL;
-
-	cur = *head;
-	while (cur != NULL) {
-		vol = be32_to_cpu(cur->vid.vol_id);
-		num = be32_to_cpu(cur->vid.lnum);
-
-		if ((vol_id == vol) && ((lnum == NULL) || (*lnum == num))) {
-			*pos = cur;
-			return 0;
-		}
-
-		cur = cur->next;
-	}
-
-	return 0;
-}
-
-
-/**
- * prints to stream, the vol_id, lnum and leb_ver for each entry in the
- * chain, starting at head;
- * this is intended for debuging purposes;
- * always returns 0;
- *
- * FIXME I do not like the double list traversion ...
- **/
-int
-eb_chain_print(FILE* stream, struct eb_info *head)
-{
-	struct eb_info *cur;
-
-	if (stream == NULL)
-		stream = stdout;
-
-	if (head == NULL) {
-		fprintf(stream, "EMPTY\n");
-		return 0;
-	}
-	/*               012345678012345678012345678012301230123 0123 01234567 0123457 01234567*/
-	fprintf(stream, "VOL_ID   LNUM     LEB_VER  EC  VID DAT  PBLK PADDR    DSIZE   EC\n");
-	cur = head;
-	while (cur != NULL) {
-		struct eb_info *hist;
-
-		fprintf(stream, "%08x %-8u %08x %-4s%-4s",
-			be32_to_cpu(cur->vid.vol_id),
-			be32_to_cpu(cur->vid.lnum),
-			be32_to_cpu(cur->vid.leb_ver),
-			cur->ec_crc_ok   ? "ok":"bad",
-			cur->vid_crc_ok  ? "ok":"bad");
-		if (cur->vid.vol_type == UBI_VID_STATIC)
-			fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"bad");
-		else	fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"ign");
-		fprintf(stream, " %-4d %08x %-8u %-8llu\n", cur->phys_block,
-			cur->phys_addr, be32_to_cpu(cur->vid.data_size),
-			(unsigned long long)be64_to_cpu(cur->ec.ec));
-
-		hist = cur->older;
-		while (hist != NULL) {
-			fprintf(stream, "%08x %-8u %08x %-4s%-4s",
-				be32_to_cpu(hist->vid.vol_id),
-				be32_to_cpu(hist->vid.lnum),
-				be32_to_cpu(hist->vid.leb_ver),
-				hist->ec_crc_ok   ? "ok":"bad",
-				hist->vid_crc_ok  ? "ok":"bad");
-			if (hist->vid.vol_type == UBI_VID_STATIC)
-				fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"bad");
-			else	fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"ign");
-			fprintf(stream, " %-4d %08x %-8u %-8llu (*)\n",
-				hist->phys_block, hist->phys_addr,
-				be32_to_cpu(hist->vid.data_size),
-				(unsigned long long)be64_to_cpu(hist->ec.ec));
-
-			hist = hist->older;
-		}
-		cur = cur->next;
-	}
-
-	return 0;
-}
-
-
-/**
- * frees the memory of the entire chain, starting at head;
- * head will be NULL on return;
- * always returns 0;
- **/
-int
-eb_chain_destroy(struct eb_info **head)
-{
-	if (head == NULL)
-		return 0;
-
-	while (*head != NULL) {
-		struct eb_info *cur;
-		struct eb_info *hist;
-
-		cur = *head;
-		*head = (*head)->next;
-
-		hist = cur->older;
-		while (hist != NULL) {
-			struct eb_info *temp;
-
-			temp = hist;
-			hist = hist->older;
-			free(temp);
-		}
-		free(cur);
-	}
-	return 0;
-}
-
diff --git a/ubi-utils/src/error.c b/ubi-utils/src/error.c
deleted file mode 100644
index 4aaedad..0000000
--- a/ubi-utils/src/error.c
+++ /dev/null
@@ -1,240 +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.
- */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <syslog.h>
-#include <stdlib.h>
-#include <sys/errno.h>
-#include <string.h>
-#include "error.h"
-
-#define MAXLINE 4096
-#define MAXWIDTH 80
-
-static FILE *logfp = NULL;
-
-static void err_doit(int, int, const char *, va_list);
-
-int
-read_procfile(FILE *fp_out, const char *procfile)
-{
-	FILE *fp;
-
-	if (!fp_out)
-		return -ENXIO;
-
-	fp = fopen(procfile, "r");
-	if (!fp)
-		return -ENOENT;
-
-	while(!feof(fp)) {
-		int c = fgetc(fp);
-
-		if (c == EOF)
-			return 0;
-
-		if (putc(c, fp_out) == EOF)
-			return -EIO;
-
-		if (ferror(fp))
-			return -EIO;
-	}
-	return fclose(fp);
-}
-
-void
-error_initlog(const char *logfile)
-{
-	if (!logfile)
-		return;
-
-	logfp = fopen(logfile, "a+");
-	read_procfile(logfp, "/proc/cpuinfo");
-}
-
-void
-info_msg(const char *fmt, ...)
-{
-	FILE* fpout;
-	char buf[MAXLINE + 1];
-	va_list	ap;
-	int n;
-
-	fpout = stdout;
-
-	va_start(ap, fmt);
-	vsnprintf(buf, MAXLINE, fmt, ap);
-	n = strlen(buf);
-	strcat(buf, "\n");
-
-	fputs(buf, fpout);
-	fflush(fpout);
-	if (fpout != stdout)
-		fclose(fpout);
-
-	va_end(ap);
-	return;
-}
-
-void
-__err_ret(const char *fmt, ...)
-{
-	va_list		ap;
-
-	va_start(ap, fmt);
-	err_doit(1, LOG_INFO, fmt, ap);
-	va_end(ap);
-	return;
-}
-
-void
-__err_sys(const char *fmt, ...)
-{
-	va_list		ap;
-
-	va_start(ap, fmt);
-	err_doit(1, LOG_ERR, fmt, ap);
-	va_end(ap);
-	exit(EXIT_FAILURE);
-}
-
-
-void
-__err_msg(const char *fmt, ...)
-{
-	va_list	ap;
-
-	va_start(ap, fmt);
-	err_doit(0, LOG_INFO, fmt, ap);
-	va_end(ap);
-
-	return;
-}
-
-void
-__err_quit(const char *fmt, ...)
-{
-	va_list		ap;
-
-	va_start(ap, fmt);
-	err_doit(0, LOG_ERR, fmt, ap);
-	va_end(ap);
-	exit(EXIT_FAILURE);
-}
-
-void
-__err_dump(const char *fmt, ...)
-{
-	va_list		ap;
-
-	va_start(ap, fmt);
-	err_doit(1, LOG_ERR, fmt, ap);
-	va_end(ap);
-	abort();		/* dump core and terminate */
-	exit(EXIT_FAILURE);	/* shouldn't get here */
-}
-
-/**
- * If a logfile is used we must not print on stderr and stdout
- * anymore. Since pfilfash might be used in a server context, it is
- * even dangerous to write to those descriptors.
- */
-static void
-err_doit(int errnoflag, int level __attribute__((unused)),
-	 const char *fmt, va_list ap)
-{
-	FILE* fpout;
-	int errno_save, n;
-	char buf[MAXLINE + 1];
-	fpout = stderr;
-
-	errno_save = errno; /* value caller might want printed */
-
-	vsnprintf(buf, MAXLINE, fmt, ap); /* safe */
-
-	n = strlen(buf);
-
-	if (errnoflag)
-		snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
-	strcat(buf, "\n");
-
-	if (logfp) {
-		fputs(buf, logfp);
-		fflush(logfp);
-		return;		/* exit when logging completes */
-	}
-
-	if (fpout == stderr) {
-		/* perform line wrap when outputting to stderr */
-		int word_len, post_len, chars;
-		char *buf_ptr;
-		const char *frmt = "%*s%n %n";
-
-		chars = 0;
-		buf_ptr = buf;
-		while (sscanf(buf_ptr, frmt, &word_len, &post_len) != EOF) {
-			int i;
-			char word[word_len + 1];
-			char post[post_len + 1];
-
-			strncpy(word, buf_ptr, word_len);
-			word[word_len] = '\0';
-			buf_ptr += word_len;
-			post_len -= word_len;
-
-			if (chars + word_len > MAXWIDTH) {
-				fputc('\n', fpout);
-				chars = 0;
-			}
-			fputs(word, fpout);
-			chars += word_len;
-
-			if (post_len > 0) {
-				strncpy(post, buf_ptr, post_len);
-				post[post_len] = '\0';
-				buf_ptr += post_len;
-			}
-			for (i = 0; i < post_len; i++) {
-				int inc = 1, chars_new;
-
-				if (post[i] == '\t')
-					inc = 8;
-				if (post[i] == '\n') {
-					inc = 0;
-					chars_new = 0;
-				} else
-					chars_new = chars + inc;
-
-				if (chars_new > MAXWIDTH) {
-					fputc('\n', fpout);
-					chars_new = inc;
-				}
-				fputc(post[i], fpout);
-				chars = chars_new;
-			}
-		}
-	}
-	else
-		fputs(buf, fpout);
-	fflush(fpout);
-	if (fpout != stderr)
-		fclose(fpout);
-
-	return;
-}
diff --git a/ubi-utils/src/error.h b/ubi-utils/src/error.h
deleted file mode 100644
index 05d8078..0000000
--- a/ubi-utils/src/error.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef __ERROR_H__
-#define __ERROR_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.
- */
-
-#include <stdio.h>
-
-void error_initlog(const char *logfile);
-int read_procfile(FILE *fp_out, const char *procfile);
-
-void __err_ret(const char *fmt, ...);
-void __err_sys(const char *fmt, ...);
-void __err_msg(const char *fmt, ...);
-void __err_quit(const char *fmt, ...);
-void __err_dump(const char *fmt, ...);
-
-void info_msg(const char *fmt, ...);
-
-#ifdef DEBUG
-#define __loc_msg(str) do {					\
-	__err_msg("[%s. FILE: %s FUNC: %s LINE: %d]\n",		\
-		str, __FILE__, __FUNCTION__, __LINE__);		\
-} while (0)
-#else
-#define __loc_msg(str)
-#endif
-
-
-#define err_dump(fmt, ...) do {					\
-	__loc_msg("ErrDump");					\
-	__err_dump(fmt, ##__VA_ARGS__);				\
-} while (0)
-
-#define err_quit(fmt, ...) do {					\
-	__loc_msg("ErrQuit");					\
-	__err_quit(fmt, ##__VA_ARGS__);				\
-} while (0)
-
-
-#define err_ret(fmt, ...) do {					\
-	__loc_msg("ErrRet");					\
-	__err_ret(fmt, ##__VA_ARGS__);				\
-} while (0)
-
-#define err_sys(fmt, ...) do {					\
-	__loc_msg("ErrSys");					\
-	__err_sys(fmt, ##__VA_ARGS__);				\
-} while (0)
-
-#define err_msg(fmt, ...) do {					\
-	__loc_msg("ErrMsg");					\
-	__err_msg(fmt, ##__VA_ARGS__);				\
-} while (0)
-
-#define log_msg(fmt, ...) do {					\
-		/* __loc_msg("LogMsg");	*/			\
-	__err_msg(fmt, ##__VA_ARGS__);				\
-} while (0)
-
-#ifdef DEBUG
-#define dbg_msg(fmt, ...) do {					\
-	__loc_msg("DbgMsg");					\
-	__err_msg(fmt, ##__VA_ARGS__);				\
-} while (0)
-#else
-#define dbg_msg(fmt, ...) do {} while (0)
-#endif
-
-#endif /* __ERROR_H__ */
diff --git a/ubi-utils/src/example_ubi.h b/ubi-utils/src/example_ubi.h
deleted file mode 100644
index 23c7b54..0000000
--- a/ubi-utils/src/example_ubi.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __EXAMPLE_UBI_H__
-#define __EXAMPLE_UBI_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.
- */
-
-/**
- * Defaults for our cards.
- */
-#define EXAMPLE_UBI_DEVICE	 0
-#define EXAMPLE_BOOTENV_VOL_ID_1 4
-#define EXAMPLE_BOOTENV_VOL_ID_2 5
-
-#endif /* __EXAMPLE_UBI_H__ */
diff --git a/ubi-utils/src/hashmap.c b/ubi-utils/src/hashmap.c
deleted file mode 100644
index 3511d56..0000000
--- a/ubi-utils/src/hashmap.c
+++ /dev/null
@@ -1,412 +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
- */
-
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "error.h"
-#include "hashmap.h"
-#define DEFAULT_BUCKETS 4096
-
-#if 0
-#define INFO_MSG(fmt...) do {	\
-	info_msg(fmt);		\
-} while (0)
-#else
-#define INFO_MSG(fmt...)
-#endif
-
-struct hashentry {
-	char* key;	/* key '0' term. str */
-	char* value;    /* payload '0' term. str */
-
-	hashentry_t next;
-};
-
-struct hashmap {
-	size_t entries;     /* current #entries */
-	size_t maxsize;     /* no. of hash buckets */
-	hashentry_t* data;  /* array of buckets */
-};
-
-static int
-is_empty(hashentry_t l)
-{
-	return l == NULL ? 1 : 0;
-}
-
-hashmap_t
-hashmap_new(void)
-{
-	hashmap_t res;
-	res = (hashmap_t) calloc(1, sizeof(struct hashmap));
-
-	if (res == NULL)
-		return NULL;
-
-	res->maxsize = DEFAULT_BUCKETS;
-	res->entries = 0;
-
-	res->data   = (hashentry_t*)
-		calloc(1, res->maxsize * sizeof(struct hashentry));
-
-	if (res->data == NULL)
-		return NULL;
-
-	return res;
-}
-
-static hashentry_t
-new_entry(const char* key, const char* value)
-{
-	hashentry_t res;
-
-	res = (hashentry_t) calloc(1, sizeof(struct hashentry));
-
-	if (res == NULL)
-		return NULL;
-
-	/* allocate key and value and copy them */
-	res->key = strdup(key);
-	if (res->key == NULL) {
-		free(res);
-		return NULL;
-	}
-
-	res->value = strdup(value);
-	if (res->value == NULL) {
-		free(res->key);
-		free(res);
-		return NULL;
-	}
-
-	res->next = NULL;
-
-	return res;
-}
-
-static hashentry_t
-free_entry(hashentry_t e)
-{
-	if (!is_empty(e)) {
-		if(e->key != NULL) {
-			free(e->key);
-		}
-		if(e->value != NULL)
-			free(e->value);
-		free(e);
-	}
-
-	return NULL;
-}
-
-static hashentry_t
-remove_entry(hashentry_t l, const char* key, size_t* entries)
-{
-	hashentry_t lnext;
-	if (is_empty(l))
-		return NULL;
-
-	if(strcmp(l->key,key) == 0) {
-		lnext = l->next;
-		l = free_entry(l);
-		(*entries)--;
-		return lnext;
-	}
-
-	l->next = remove_entry(l->next, key, entries);
-
-	return l;
-}
-
-static hashentry_t
-insert_entry(hashentry_t l, hashentry_t e, size_t* entries)
-{
-	if (is_empty(l)) {
-		(*entries)++;
-		return e;
-	}
-
-	/* check for update */
-	if (strcmp(l->key, e->key) == 0) {
-		e->next = l->next;
-		l = free_entry(l);
-		return e;
-	}
-
-	l->next = insert_entry(l->next, e, entries);
-	return l;
-}
-
-static hashentry_t
-remove_all(hashentry_t l, size_t* entries)
-{
-	hashentry_t lnext;
-	if (is_empty(l))
-		return NULL;
-
-	lnext = l->next;
-	free_entry(l);
-	(*entries)--;
-
-	return remove_all(lnext, entries);
-}
-
-static const char*
-value_lookup(hashentry_t l, const char* key)
-{
-	if (is_empty(l))
-		return NULL;
-
-	if (strcmp(l->key, key) == 0)
-		return l->value;
-
-	return value_lookup(l->next, key);
-}
-
-static void
-print_all(hashentry_t l)
-{
-	if (is_empty(l)) {
-		printf("\n");
-		return;
-	}
-
-	printf("%s=%s", l->key, l->value);
-	if (!is_empty(l->next)) {
-		printf(",");
-	}
-
-	print_all(l->next);
-}
-
-static void
-keys_to_array(hashentry_t l, const char** a, size_t* i)
-{
-	if (is_empty(l))
-		return;
-
-	a[*i] = l->key;
-	(*i)++;
-
-	keys_to_array(l->next, a, i);
-}
-
-uint32_t
-hash_str(const char* str, uint32_t mapsize)
-{
-	uint32_t hash = 0;
-	uint32_t x    = 0;
-	uint32_t i    = 0;
-	size_t   len  = strlen(str);
-
-	for(i = 0; i < len; str++, i++)	{
-		hash = (hash << 4) + (*str);
-		if((x = hash & 0xF0000000L) != 0) {
-			hash ^= (x >> 24);
-			hash &= ~x;
-		}
-	}
-
-	return (hash & 0x7FFFFFFF) % mapsize;
-}
-
-
-int
-hashmap_is_empty(hashmap_t map)
-{
-	if (map == NULL)
-		return -EINVAL;
-
-	return map->entries > 0 ? 1 : 0;
-}
-
-const char*
-hashmap_lookup(hashmap_t map, const char* key)
-{
-	uint32_t i;
-
-	if ((map == NULL) || (key == NULL))
-		return NULL;
-
-	i = hash_str(key, map->maxsize);
-
-	return value_lookup(map->data[i], key);
-}
-
-int
-hashmap_add(hashmap_t map, const char* key, const char* value)
-{
-	uint32_t i;
-	hashentry_t entry;
-
-	if ((map == NULL) || (key == NULL) || (value == NULL))
-		return -EINVAL;
-
-	i = hash_str(key, map->maxsize);
-	entry = new_entry(key, value);
-	if (entry == NULL)
-		return -ENOMEM;
-
-	map->data[i] = insert_entry(map->data[i],
-			entry, &map->entries);
-
-	INFO_MSG("HASH_ADD: chain[%d] key:%s val:%s",i,  key, value);
-	return 0;
-}
-
-int
-hashmap_remove(hashmap_t map, const char* key)
-{
-	uint32_t i;
-
-	if ((map == NULL) || (key == NULL))
-		return -EINVAL;
-
-	i = hash_str(key, map->maxsize);
-	map->data[i] = remove_entry(map->data[i], key, &map->entries);
-
-	return 0;
-}
-
-size_t
-hashmap_size(hashmap_t map)
-{
-	if (map != NULL)
-		return map->entries;
-	else
-		return 0;
-}
-
-int
-hashmap_free(hashmap_t map)
-{
-	size_t i;
-
-	if (map == NULL)
-		return -EINVAL;
-
-	/* "children" first */
-	for(i = 0; i < map->maxsize; i++) {
-		map->data[i] = remove_all(map->data[i], &map->entries);
-	}
-	free(map->data);
-	free(map);
-
-	return 0;
-}
-
-int
-hashmap_dump(hashmap_t map)
-{
-	size_t i;
-	if (map == NULL)
-		return -EINVAL;
-
-	for(i = 0; i < map->maxsize; i++) {
-		if (map->data[i] != NULL) {
-			printf("[%zd]: ", i);
-			print_all(map->data[i]);
-		}
-	}
-
-	return 0;
-}
-
-static const char**
-sort_key_vector(const char** a, size_t size)
-{
-	/* uses bubblesort */
-	size_t i, j;
-	const char* tmp;
-
-	if (size <= 0)
-		return a;
-
-	for (i = size - 1; i > 0; i--) {
-		for (j = 0; j < i; j++) {
-			if (strcmp(a[j], a[j+1]) > 0) {
-				tmp  = a[j];
-				a[j] = a[j+1];
-				a[j+1] = tmp;
-			}
-		}
-	}
-	return a;
-}
-
-const char**
-hashmap_get_key_vector(hashmap_t map, size_t* size, int sort)
-{
-	const char** res;
-	size_t i, j;
-	*size = map->entries;
-
-	res = (const char**) malloc(*size * sizeof(char*));
-	if (res == NULL)
-		return NULL;
-
-	j = 0;
-	for(i=0; i < map->maxsize; i++) {
-		keys_to_array(map->data[i], res, &j);
-	}
-
-	if (sort)
-		res = sort_key_vector(res, *size);
-
-	return res;
-}
-
-int
-hashmap_key_is_in_vector(const char** vec, size_t size, const char* key)
-{
-	size_t i;
-	for (i = 0; i < size; i++) {
-		if (strcmp(vec[i], key) == 0) /* found */
-			return 1;
-	}
-
-	return 0;
-}
-
-const char**
-hashmap_get_update_key_vector(const char** vec1, size_t vec1_size,
-		const char** vec2, size_t vec2_size, size_t* res_size)
-{
-	const char** res;
-	size_t i, j;
-
-	*res_size = vec2_size;
-
-	res = (const char**) malloc(*res_size * sizeof(char*));
-	if (res == NULL)
-		return NULL;
-
-	/* get all keys from vec2 which are not set in vec1 */
-	j = 0;
-	for (i = 0; i < vec2_size; i++) {
-		if (!hashmap_key_is_in_vector(vec1, vec1_size, vec2[i]))
-			res[j++] = vec2[i];
-	}
-
-	*res_size = j;
-	return res;
-}
diff --git a/ubi-utils/src/hashmap.h b/ubi-utils/src/hashmap.h
deleted file mode 100644
index 1b13e95..0000000
--- a/ubi-utils/src/hashmap.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef __HASHMAP_H__
-#define __HASHMAP_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: Oliver Lohmann
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-
-typedef struct hashentry *hashentry_t;
-typedef struct hashmap *hashmap_t;
-
-hashmap_t hashmap_new(void);
-int hashmap_free(hashmap_t map);
-
-int hashmap_add(hashmap_t map, const char* key, const char* value);
-int hashmap_update(hashmap_t map, const char* key, const char* value);
-int hashmap_remove(hashmap_t map, const char* key);
-const char* hashmap_lookup(hashmap_t map, const char* key);
-
-const char** hashmap_get_key_vector(hashmap_t map, size_t* size, int sort);
-int hashmap_key_is_in_vector(const char** vec, size_t size, const char* key);
-const char** hashmap_get_update_key_vector(const char** vec1, size_t vec1_size,
-		const char** vec2, size_t vec2_size, size_t* res_size);
-
-int hashmap_dump(hashmap_t map);
-
-int hashmap_is_empty(hashmap_t map);
-size_t hashmap_size(hashmap_t map);
-
-uint32_t hash_str(const char* str, uint32_t mapsize);
-
-#endif /* __HASHMAP_H__ */
diff --git a/ubi-utils/src/libiniparser.c b/ubi-utils/src/libiniparser.c
new file mode 100644
index 0000000..3bea51e
--- /dev/null
+++ b/ubi-utils/src/libiniparser.c
@@ -0,0 +1,646 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+   @file    iniparser.c
+   @author  N. Devillard
+   @date    Sep 2007
+   @version 3.0
+   @brief   Parser for ini files.
+*/
+/*--------------------------------------------------------------------------*/
+/*
+    $Id: iniparser.c,v 2.18 2008-01-03 18:35:39 ndevilla Exp $
+    $Revision: 2.18 $
+    $Date: 2008-01-03 18:35:39 $
+*/
+/*---------------------------- Includes ------------------------------------*/
+#include <ctype.h>
+#include <libiniparser.h>
+
+/*---------------------------- Defines -------------------------------------*/
+#define ASCIILINESZ         (1024)
+#define INI_INVALID_KEY     ((char*)-1)
+
+/*---------------------------------------------------------------------------
+                        Private to this module
+ ---------------------------------------------------------------------------*/
+/**
+ * This enum stores the status for each parsed line (internal use only).
+ */
+typedef enum _line_status_ {
+    LINE_UNPROCESSED,
+    LINE_ERROR,
+    LINE_EMPTY,
+    LINE_COMMENT,
+    LINE_SECTION,
+    LINE_VALUE
+} line_status ;
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Convert a string to lowercase.
+  @param	s	String to convert.
+  @return	ptr to statically allocated string.
+
+  This function returns a pointer to a statically allocated string
+  containing a lowercased version of the input string. Do not free
+  or modify the returned string! Since the returned string is statically
+  allocated, it will be modified at each function call (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+static char * strlwc(const char * s)
+{
+    static char l[ASCIILINESZ+1];
+    int i ;
+
+    if (s==NULL) return NULL ;
+    memset(l, 0, ASCIILINESZ+1);
+    i=0 ;
+    while (s[i] && i<ASCIILINESZ) {
+        l[i] = (char)tolower((int)s[i]);
+        i++ ;
+    }
+    l[ASCIILINESZ]=(char)0;
+    return l ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Remove blanks at the beginning and the end of a string.
+  @param	s	String to parse.
+  @return	ptr to statically allocated string.
+
+  This function returns a pointer to a statically allocated string,
+  which is identical to the input string, except that all blank
+  characters at the end and the beg. of the string have been removed.
+  Do not free or modify the returned string! Since the returned string
+  is statically allocated, it will be modified at each function call
+  (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+static char * strstrip(char * s)
+{
+    static char l[ASCIILINESZ+1];
+	char * last ;
+	
+    if (s==NULL) return NULL ;
+    
+	while (isspace((int)*s) && *s) s++;
+	memset(l, 0, ASCIILINESZ+1);
+	strcpy(l, s);
+	last = l + strlen(l);
+	while (last > l) {
+		if (!isspace((int)*(last-1)))
+			break ;
+		last -- ;
+	}
+	*last = (char)0;
+	return (char*)l ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get number of sections in a dictionary
+  @param    d   Dictionary to examine
+  @return   int Number of sections found in dictionary
+
+  This function returns the number of sections found in a dictionary.
+  The test to recognize sections is done on the string stored in the
+  dictionary: a section name is given as "section" whereas a key is
+  stored as "section:key", thus the test looks for entries that do not
+  contain a colon.
+
+  This clearly fails in the case a section name contains a colon, but
+  this should simply be avoided.
+
+  This function returns -1 in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getnsec(dictionary * d)
+{
+    int i ;
+    int nsec ;
+
+    if (d==NULL) return -1 ;
+    nsec=0 ;
+    for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        if (strchr(d->key[i], ':')==NULL) {
+            nsec ++ ;
+        }
+    }
+    return nsec ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get name for section n in a dictionary.
+  @param    d   Dictionary to examine
+  @param    n   Section number (from 0 to nsec-1).
+  @return   Pointer to char string
+
+  This function locates the n-th section in a dictionary and returns
+  its name as a pointer to a string statically allocated inside the
+  dictionary. Do not free or modify the returned string!
+
+  This function returns NULL in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getsecname(dictionary * d, int n)
+{
+    int i ;
+    int foundsec ;
+
+    if (d==NULL || n<0) return NULL ;
+    foundsec=0 ;
+    for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        if (strchr(d->key[i], ':')==NULL) {
+            foundsec++ ;
+            if (foundsec>n)
+                break ;
+        }
+    }
+    if (foundsec<=n) {
+        return NULL ;
+    }
+    return d->key[i] ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Dump a dictionary to an opened file pointer.
+  @param    d   Dictionary to dump.
+  @param    f   Opened file pointer to dump to.
+  @return   void
+
+  This function prints out the contents of a dictionary, one element by
+  line, onto the provided file pointer. It is OK to specify @c stderr
+  or @c stdout as output files. This function is meant for debugging
+  purposes mostly.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_dump(dictionary * d, FILE * f)
+{
+    int     i ;
+
+    if (d==NULL || f==NULL) return ;
+    for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        if (d->val[i]!=NULL) {
+            fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
+        } else {
+            fprintf(f, "[%s]=UNDEF\n", d->key[i]);
+        }
+    }
+    return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Save a dictionary to a loadable ini file
+  @param    d   Dictionary to dump
+  @param    f   Opened file pointer to dump to
+  @return   void
+
+  This function dumps a given dictionary into a loadable ini file.
+  It is Ok to specify @c stderr or @c stdout as output files.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_dump_ini(dictionary * d, FILE * f)
+{
+    int     i, j ;
+    char    keym[ASCIILINESZ+1];
+    int     nsec ;
+    char *  secname ;
+    int     seclen ;
+
+    if (d==NULL || f==NULL) return ;
+
+    nsec = iniparser_getnsec(d);
+    if (nsec<1) {
+        /* No section in file: dump all keys as they are */
+        for (i=0 ; i<d->size ; i++) {
+            if (d->key[i]==NULL)
+                continue ;
+            fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
+        }
+        return ;
+    }
+    for (i=0 ; i<nsec ; i++) {
+        secname = iniparser_getsecname(d, i) ;
+        seclen  = (int)strlen(secname);
+        fprintf(f, "\n[%s]\n", secname);
+        sprintf(keym, "%s:", secname);
+        for (j=0 ; j<d->size ; j++) {
+            if (d->key[j]==NULL)
+                continue ;
+            if (!strncmp(d->key[j], keym, seclen+1)) {
+                fprintf(f,
+                        "%-30s = %s\n",
+                        d->key[j]+seclen+1,
+                        d->val[j] ? d->val[j] : "");
+            }
+        }
+    }
+    fprintf(f, "\n");
+    return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key
+  @param    d       Dictionary to search
+  @param    key     Key string to look for
+  @param    def     Default value to return if key not found.
+  @return   pointer to statically allocated character string
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the pointer passed as 'def' is returned.
+  The returned char pointer is pointing to a string allocated in
+  the dictionary, do not free or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getstring(dictionary * d, const char * key, char * def)
+{
+    char * lc_key ;
+    char * sval ;
+
+    if (d==NULL || key==NULL)
+        return def ;
+
+    lc_key = strlwc(key);
+    sval = dictionary_get(d, lc_key, def);
+    return sval ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key, convert to an int
+  @param    d Dictionary to search
+  @param    key Key string to look for
+  @param    notfound Value to return in case of error
+  @return   integer
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the notfound value is returned.
+
+  Supported values for integers include the usual C notation
+  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
+  are supported. Examples:
+
+  "42"      ->  42
+  "042"     ->  34 (octal -> decimal)
+  "0x42"    ->  66 (hexa  -> decimal)
+
+  Warning: the conversion may overflow in various ways. Conversion is
+  totally outsourced to strtol(), see the associated man page for overflow
+  handling.
+
+  Credits: Thanks to A. Becker for suggesting strtol()
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getint(dictionary * d, const char * key, int notfound)
+{
+    char    *   str ;
+
+    str = iniparser_getstring(d, key, INI_INVALID_KEY);
+    if (str==INI_INVALID_KEY) return notfound ;
+    return (int)strtol(str, NULL, 0);
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key, convert to a double
+  @param    d Dictionary to search
+  @param    key Key string to look for
+  @param    notfound Value to return in case of error
+  @return   double
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the notfound value is returned.
+ */
+/*--------------------------------------------------------------------------*/
+double iniparser_getdouble(dictionary * d, char * key, double notfound)
+{
+    char    *   str ;
+
+    str = iniparser_getstring(d, key, INI_INVALID_KEY);
+    if (str==INI_INVALID_KEY) return notfound ;
+    return atof(str);
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key, convert to a boolean
+  @param    d Dictionary to search
+  @param    key Key string to look for
+  @param    notfound Value to return in case of error
+  @return   integer
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the notfound value is returned.
+
+  A true boolean is found if one of the following is matched:
+
+  - A string starting with 'y'
+  - A string starting with 'Y'
+  - A string starting with 't'
+  - A string starting with 'T'
+  - A string starting with '1'
+
+  A false boolean is found if one of the following is matched:
+
+  - A string starting with 'n'
+  - A string starting with 'N'
+  - A string starting with 'f'
+  - A string starting with 'F'
+  - A string starting with '0'
+
+  The notfound value returned if no boolean is identified, does not
+  necessarily have to be 0 or 1.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getboolean(dictionary * d, const char * key, int notfound)
+{
+    char    *   c ;
+    int         ret ;
+
+    c = iniparser_getstring(d, key, INI_INVALID_KEY);
+    if (c==INI_INVALID_KEY) return notfound ;
+    if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
+        ret = 1 ;
+    } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
+        ret = 0 ;
+    } else {
+        ret = notfound ;
+    }
+    return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Finds out if a given entry exists in a dictionary
+  @param    ini     Dictionary to search
+  @param    entry   Name of the entry to look for
+  @return   integer 1 if entry exists, 0 otherwise
+
+  Finds out if a given entry exists in the dictionary. Since sections
+  are stored as keys with NULL associated values, this is the only way
+  of querying for the presence of sections in a dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_find_entry(
+    dictionary  *   ini,
+    char        *   entry
+)
+{
+    int found=0 ;
+    if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
+        found = 1 ;
+    }
+    return found ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Set an entry in a dictionary.
+  @param    ini     Dictionary to modify.
+  @param    entry   Entry to modify (entry name)
+  @param    val     New value to associate to the entry.
+  @return   int 0 if Ok, -1 otherwise.
+
+  If the given entry can be found in the dictionary, it is modified to
+  contain the provided value. If it cannot be found, -1 is returned.
+  It is Ok to set val to NULL.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_set(dictionary * ini, char * entry, char * val)
+{
+    return dictionary_set(ini, strlwc(entry), val) ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Delete an entry in a dictionary
+  @param    ini     Dictionary to modify
+  @param    entry   Entry to delete (entry name)
+  @return   void
+
+  If the given entry can be found, it is deleted from the dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_unset(dictionary * ini, char * entry)
+{
+    dictionary_unset(ini, strlwc(entry));
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Load a single line from an INI file
+  @param    input_line  Input line, may be concatenated multi-line input
+  @param    section     Output space to store section
+  @param    key         Output space to store key
+  @param    value       Output space to store value
+  @return   line_status value
+ */
+/*--------------------------------------------------------------------------*/
+static line_status iniparser_line(
+    char * input_line,
+    char * section,
+    char * key,
+    char * value)
+{   
+    line_status sta ;
+    char        line[ASCIILINESZ+1];
+    int         len ;
+
+    strcpy(line, strstrip(input_line));
+    len = (int)strlen(line);
+
+    sta = LINE_UNPROCESSED ;
+    if (len<1) {
+        /* Empty line */
+        sta = LINE_EMPTY ;
+    } else if (line[0]=='#') {
+        /* Comment line */
+        sta = LINE_COMMENT ; 
+    } else if (line[0]=='[' && line[len-1]==']') {
+        /* Section name */
+        sscanf(line, "[%[^]]", section);
+        strcpy(section, strstrip(section));
+        strcpy(section, strlwc(section));
+        sta = LINE_SECTION ;
+    } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
+           ||  sscanf (line, "%[^=] = '%[^\']'",   key, value) == 2
+           ||  sscanf (line, "%[^=] = %[^;#]",     key, value) == 2) {
+        /* Usual key=value, with or without comments */
+        strcpy(key, strstrip(key));
+        strcpy(key, strlwc(key));
+        strcpy(value, strstrip(value));
+        /*
+         * sscanf cannot handle '' or "" as empty values
+         * this is done here
+         */
+        if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
+            value[0]=0 ;
+        }
+        sta = LINE_VALUE ;
+    } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
+           ||  sscanf(line, "%[^=] %[=]", key, value) == 2) {
+        /*
+         * Special cases:
+         * key=
+         * key=;
+         * key=#
+         */
+        strcpy(key, strstrip(key));
+        strcpy(key, strlwc(key));
+        value[0]=0 ;
+        sta = LINE_VALUE ;
+    } else {
+        /* Generate syntax error */
+        sta = LINE_ERROR ;
+    }
+    return sta ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Parse an ini file and return an allocated dictionary object
+  @param    ininame Name of the ini file to read.
+  @return   Pointer to newly allocated dictionary
+
+  This is the parser for ini files. This function is called, providing
+  the name of the file to be read. It returns a dictionary object that
+  should not be accessed directly, but through accessor functions
+  instead.
+
+  The returned dictionary must be freed using iniparser_freedict().
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * iniparser_load(const char * ininame)
+{
+    FILE * in ;
+
+    char line    [ASCIILINESZ+1] ;
+    char section [ASCIILINESZ+1] ;
+    char key     [ASCIILINESZ+1] ;
+    char tmp     [ASCIILINESZ+1] ;
+    char val     [ASCIILINESZ+1] ;
+
+    int  last=0 ;
+    int  len ;
+    int  lineno=0 ;
+    int  errs=0;
+
+    dictionary * dict ;
+
+    if ((in=fopen(ininame, "r"))==NULL) {
+        fprintf(stderr, "iniparser: cannot open %s\n", ininame);
+        return NULL ;
+    }
+
+    dict = dictionary_new(0) ;
+    if (!dict) {
+        fclose(in);
+        return NULL ;
+    }
+
+    memset(line,    0, ASCIILINESZ);
+    memset(section, 0, ASCIILINESZ);
+    memset(key,     0, ASCIILINESZ);
+    memset(val,     0, ASCIILINESZ);
+    last=0 ;
+
+    while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
+        lineno++ ;
+        len = (int)strlen(line)-1;
+        /* Safety check against buffer overflows */
+        if (line[len]!='\n') {
+            fprintf(stderr,
+                    "iniparser: input line too long in %s (%d)\n",
+                    ininame,
+                    lineno);
+            dictionary_del(dict);
+            fclose(in);
+            return NULL ;
+        }
+        /* Get rid of \n and spaces at end of line */
+        while ((len>=0) &&
+                ((line[len]=='\n') || (isspace(line[len])))) {
+            line[len]=0 ;
+            len-- ;
+        }
+        /* Detect multi-line */
+        if (line[len]=='\\') {
+            /* Multi-line value */
+            last=len ;
+            continue ;
+        } else {
+            last=0 ;
+        }
+        switch (iniparser_line(line, section, key, val)) {
+            case LINE_EMPTY:
+            case LINE_COMMENT:
+            break ;
+
+            case LINE_SECTION:
+            errs = dictionary_set(dict, section, NULL);
+            break ;
+
+            case LINE_VALUE:
+            sprintf(tmp, "%s:%s", section, key);
+            errs = dictionary_set(dict, tmp, val) ;
+            break ;
+
+            case LINE_ERROR:
+            fprintf(stderr, "iniparser: syntax error in %s (%d):\n",
+                    ininame,
+                    lineno);
+            fprintf(stderr, "-> %s\n", line);
+            errs++ ;
+            break;
+
+            default:
+            break ;
+        }
+        memset(line, 0, ASCIILINESZ);
+        last=0;
+        if (errs<0) {
+            fprintf(stderr, "iniparser: memory allocation failure\n");
+            break ;
+        }
+    }
+    if (errs) {
+        dictionary_del(dict);
+        dict = NULL ;
+    }
+    fclose(in);
+    return dict ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Free all memory associated to an ini dictionary
+  @param    d Dictionary to free
+  @return   void
+
+  Free all memory associated to an ini dictionary.
+  It is mandatory to call this function before the dictionary object
+  gets out of the current context.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_freedict(dictionary * d)
+{
+    dictionary_del(d);
+}
+
+/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/ubi-utils/src/libmtd.c b/ubi-utils/src/libmtd.c
new file mode 100644
index 0000000..b60ddbd
--- /dev/null
+++ b/ubi-utils/src/libmtd.c
@@ -0,0 +1,314 @@
+/*
+ * 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.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * MTD library.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <mtd/mtd-user.h>
+#include <libmtd.h>
+#include "common.h"
+
+#define PROGRAM_NAME "libmtd"
+#define MTD_DEV_MAJOR 90
+
+/**
+ * mtd_get_info - get information about an MTD device.
+ * @node: name of the MTD device node
+ * @mtd: the MTD device information is returned here
+ *
+ * This function gets information about MTD device defined by the @node device
+ * node file and saves this information in the @mtd object. Returns %0 in case
+ * of success and %-1 in case of failure.
+ */
+int mtd_get_info(const char *node, struct mtd_info *mtd)
+{
+	struct stat st;
+	struct mtd_info_user ui;
+	int ret;
+	loff_t offs = 0;
+
+	if (stat(node, &st))
+		return sys_errmsg("cannot open \"%s\"", node);
+
+	if (!S_ISCHR(st.st_mode)) {
+		errno = EINVAL;
+		return errmsg("\"%s\" is not a character device", node);
+	}
+
+	mtd->major = major(st.st_rdev);
+	mtd->minor = minor(st.st_rdev);
+
+	if (mtd->major != MTD_DEV_MAJOR) {
+		errno = EINVAL;
+		return errmsg("\"%s\" has major number %d, MTD devices have "
+			      "major %d", node, mtd->major, MTD_DEV_MAJOR);
+	}
+
+	mtd->num = mtd->minor / 2;
+	mtd->rdonly = mtd->minor & 1;
+
+	mtd->fd = open(node, O_RDWR);
+	if (mtd->fd == -1)
+		return sys_errmsg("cannot open \"%s\"", node);
+
+	if (ioctl(mtd->fd, MEMGETINFO, &ui)) {
+		sys_errmsg("MEMGETINFO ioctl request failed");
+		goto out_close;
+	}
+
+	ret = ioctl(mtd->fd, MEMGETBADBLOCK, &offs);
+	if (ret == -1) {
+		if (errno != EOPNOTSUPP) {
+			sys_errmsg("MEMGETBADBLOCK ioctl failed");
+			goto out_close;
+		}
+		errno = 0;
+		mtd->allows_bb = 0;
+	} else
+		mtd->allows_bb = 1;
+
+	mtd->type = ui.type;
+	mtd->size = ui.size;
+	mtd->eb_size = ui.erasesize;
+	mtd->min_io_size = ui.writesize;
+
+	if (mtd->min_io_size <= 0) {
+		errmsg("mtd%d (%s) has insane min. I/O unit size %d",
+		       mtd->num, node, mtd->min_io_size);
+		goto out_close;
+	}
+	if (mtd->eb_size <= 0 || mtd->eb_size < mtd->min_io_size) {
+		errmsg("mtd%d (%s) has insane eraseblock size %d",
+		       mtd->num, node, mtd->eb_size);
+		goto out_close;
+	}
+	if (mtd->size <= 0 || mtd->size < mtd->eb_size) {
+		errmsg("mtd%d (%s) has insane size %lld",
+		       mtd->num, node, mtd->size);
+		goto out_close;
+	}
+	mtd->eb_cnt = mtd->size / mtd->eb_size;
+
+	switch(mtd->type) {
+	case MTD_ABSENT:
+		errmsg("mtd%d (%s) is removable and is not present",
+		       mtd->num, node);
+		goto out_close;
+	case MTD_RAM:
+		mtd->type_str = "RAM-based";
+		break;
+	case MTD_ROM:
+		mtd->type_str = "ROM";
+		break;
+	case MTD_NORFLASH:
+		mtd->type_str = "NOR";
+		break;
+	case MTD_NANDFLASH:
+		mtd->type_str = "NAND";
+		break;
+	case MTD_DATAFLASH:
+		mtd->type_str = "DataFlash";
+		break;
+	case MTD_UBIVOLUME:
+		mtd->type_str = "UBI-emulated MTD";
+		break;
+	default:
+		mtd->type_str = "Unknown flash type";
+		break;
+	}
+
+	if (!(ui.flags & MTD_WRITEABLE))
+		mtd->rdonly = 1;
+
+	return 0;
+
+out_close:
+	close(mtd->fd);
+	return -1;
+}
+
+/**
+ * mtd_erase - erase an eraseblock.
+ * @mtd: MTD device description object
+ * @eb: eraseblock to erase
+ *
+ * This function erases the eraseblock and returns %0 in case of success and
+ * %-1 in case of failure.
+ */
+int mtd_erase(const struct mtd_info *mtd, int eb)
+{
+	struct erase_info_user ei;
+
+	ei.start = eb * mtd->eb_size;;
+	ei.length = mtd->eb_size;
+	return ioctl(mtd->fd, MEMERASE, &ei);
+}
+
+/**
+ * mtd_is_bad - check if eraseblock is bad.
+ * @mtd: MTD device description object
+ * @eb: eraseblock to check
+ *
+ * This function checks if eraseblock @eb is bad. Returns %0 if not, %1 if yes,
+ * and %-1 in case of failure.
+ */
+int mtd_is_bad(const struct mtd_info *mtd, int eb)
+{
+	int ret;
+	loff_t seek;
+
+	if (eb < 0 || eb >= mtd->eb_cnt) {
+		errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks",
+		       eb, mtd->num, mtd->eb_cnt);
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (!mtd->allows_bb)
+		return 0;
+
+	seek = (loff_t)eb * mtd->eb_size;
+	ret = ioctl(mtd->fd, MEMGETBADBLOCK, &seek);
+	if (ret == -1) {
+		sys_errmsg("MEMGETBADBLOCK ioctl failed for "
+			   "eraseblock %d (mtd%d)", eb, mtd->num);
+		return -1;
+	}
+
+	return ret;
+}
+
+/**
+ * mtd_read - read data from an MTD device.
+ * @mtd: MTD device description object
+ * @eb: eraseblock to read from
+ * @offs: offset withing the eraseblock to read from
+ * @buf: buffer to read data to
+ * @len: how many bytes to read
+ *
+ * This function reads @len bytes of data from eraseblock @eb and offset @offs
+ * of the MTD device defined by @mtd and stores the read data at buffer @buf.
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+int mtd_read(const struct mtd_info *mtd, int eb, int offs, void *buf, int len)
+{
+	int ret, rd = 0;
+	off_t seek;
+
+	if (eb < 0 || eb >= mtd->eb_cnt) {
+		errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks",
+		       eb, mtd->num, mtd->eb_cnt);
+		errno = EINVAL;
+		return -1;
+	}
+	if (offs < 0 || offs + len > mtd->eb_size) {
+		errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d",
+		       offs, len, mtd->num, mtd->eb_size);
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Seek to the beginning of the eraseblock */
+	seek = (off_t)eb * mtd->eb_size + offs;
+	if (lseek(mtd->fd, seek, SEEK_SET) != seek) {
+		sys_errmsg("cannot seek mtd%d to offset %llu",
+			   mtd->num, (unsigned long long)seek);
+		return -1;
+	}
+
+	while (rd < len) {
+		ret = read(mtd->fd, buf, len);
+		if (ret < 0) {
+			sys_errmsg("cannot read %d bytes from mtd%d (eraseblock %d, offset %d)",
+				   len, mtd->num, eb, offs);
+			return -1;
+		}
+		rd += ret;
+	}
+
+	return 0;
+}
+
+/**
+ * mtd_write - write data to an MTD device.
+ * @mtd: MTD device description object
+ * @eb: eraseblock to write to
+ * @offs: offset withing the eraseblock to write to
+ * @buf: buffer to write
+ * @len: how many bytes to write
+ *
+ * This function writes @len bytes of data to eraseblock @eb and offset @offs
+ * of the MTD device defined by @mtd. Returns %0 in case of success and %-1 in
+ * case of failure.
+ */
+int mtd_write(const struct mtd_info *mtd, int eb, int offs, void *buf, int len)
+{
+	int ret;
+	off_t seek;
+
+	if (eb < 0 || eb >= mtd->eb_cnt) {
+		errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks",
+		       eb, mtd->num, mtd->eb_cnt);
+		errno = EINVAL;
+		return -1;
+	}
+	if (offs < 0 || offs + len > mtd->eb_size) {
+		errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d",
+		       offs, len, mtd->num, mtd->eb_size);
+		errno = EINVAL;
+		return -1;
+	}
+#if 0
+	if (offs % mtd->subpage_size) {
+		errmsg("write offset %d is not aligned to mtd%d min. I/O size %d",
+		       offs, mtd->num, mtd->subpage_size);
+		errno = EINVAL;
+		return -1;
+	}
+	if (len % mtd->subpage_size) {
+		errmsg("write length %d is not aligned to mtd%d min. I/O size %d",
+		       len, mtd->num, mtd->subpage_size);
+		errno = EINVAL;
+		return -1;
+	}
+#endif
+
+	/* Seek to the beginning of the eraseblock */
+	seek = (off_t)eb * mtd->eb_size + offs;
+	if (lseek(mtd->fd, seek, SEEK_SET) != seek) {
+		sys_errmsg("cannot seek mtd%d to offset %llu",
+			   mtd->num, (unsigned long long)seek);
+		return -1;
+	}
+
+	ret = write(mtd->fd, buf, len);
+	if (ret != len) {
+		sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)",
+			   len, mtd->num, eb, offs);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/ubi-utils/src/libpfiflash.c b/ubi-utils/src/libpfiflash.c
deleted file mode 100644
index b0d454a..0000000
--- a/ubi-utils/src/libpfiflash.c
+++ /dev/null
@@ -1,1325 +0,0 @@
-/*
- * Copyright International Business Machines Corp., 2006, 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.
- */
-
-/*
- * Authors: Oliver Lohmann <oliloh@de.ibm.com>
- *	    Drake Dowsett <dowsett@de.ibm.com>
- * Contact: Andreas Arnez <anrez@de.ibm.com>
- */
-
-/* TODO Compare data before writing it. This implies that the volume
- * parameters are compared first: size, alignment, name, type, ...,
- * this is the same, compare the data. Volume deletion is deffered
- * until the difference has been found out.
- */
-
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#define __USE_GNU
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <sys/ioctl.h>
-
-#include <libubi.h>
-#include <pfiflash.h>
-
-#include <mtd/ubi-user.h>	/* FIXME Is this ok here? */
-#include <mtd/mtd-user.h>
-
-#include "pfiflash_error.h"
-#include "ubimirror.h"
-#include "error.h"
-#include "reader.h"
-#include "example_ubi.h"
-#include "bootenv.h"
-
-/* ubi-header.h and crc32.h needed for CRC checking */
-#include <mtd/ubi-media.h>	/* FIXME Is this ok here? */
-#include "crc32.h"
-
-#define ubi_unused __attribute__((unused))
-
-#define COMPARE_BUFFER_SIZE 2048
-
-#define DEFAULT_DEV_PATTERN    "/dev/ubi%d"
-#define DEFAULT_VOL_PATTERN    "/dev/ubi%d_%d"
-
-static const char copyright [] ubi_unused =
-	"Copyright International Business Machines Corp., 2006, 2007";
-
-/* simply clear buffer, then write into front of it */
-#define EBUF(fmt...)							\
-		snprintf(err_buf, err_buf_size, fmt);
-
-/* make a history of buffer and then prepend something in front */
-#define EBUF_PREPEND(fmt)						\
-	do {								\
-		int EBUF_HISTORY_LENGTH = strlen(err_buf);		\
-		char EBUF_HISTORY[EBUF_HISTORY_LENGTH + 1];		\
-		strncpy(EBUF_HISTORY, err_buf, EBUF_HISTORY_LENGTH + 1);\
-		EBUF(fmt ": %s", EBUF_HISTORY);				\
-	} while (0)
-
-/* An array of PDD function pointers indexed by the algorithm. */
-static pdd_func_t pdd_funcs[PDD_HANDLING_NUM]  =
-	{
-		&bootenv_pdd_keep,
-		&bootenv_pdd_merge,
-		&bootenv_pdd_overwrite
-	};
-
-typedef enum ubi_update_process_t {
-	UBI_REMOVE = 0,
-	UBI_WRITE,
-	UBI_COMPARE,
-} ubi_update_process_t;
-
-
-/**
- * skip_raw_volumes - reads data from pfi to advance fp past raw block
- * @pfi:	fp to pfi data
- * @pfi_raws:	header information
- *
- * Error handling):
- *	when early EOF in pfi data
- *	- returns -PFIFLASH_ERR_EOF, err_buf matches text to err
- *	when file I/O error
- *	- returns -PFIFLASH_ERR_FIO, err_buf matches text to err
- **/
-static int
-skip_raw_volumes(FILE* pfi, list_t pfi_raws,
-		  char* err_buf, size_t err_buf_size)
-{
-	int rc;
-	void *i;
-	list_t ptr;
-
-	if (is_empty(pfi_raws))
-		return 0;
-
-	rc = 0;
-	foreach(i, ptr, pfi_raws) {
-		size_t j;
-		pfi_raw_t raw;
-
-		raw = (pfi_raw_t)i;
-		for(j = 0; j < raw->data_size; j++) {
-			int c;
-
-			c = fgetc(pfi);
-			if (c == EOF)
-				rc = -PFIFLASH_ERR_EOF;
-			else if (ferror(pfi))
-				rc = -PFIFLASH_ERR_FIO;
-
-			if (rc != 0)
-				goto err;
-		}
-	}
-
- err:
-	EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-	return rc;
-}
-
-
-/**
- * my_ubi_mkvol - wraps the ubi_mkvol functions and impl. bootenv update hook
- * @devno:	UBI device number.
- * @s:		Current seqnum.
- * @u:		Information about the UBI volume from the PFI.
- *
- * Error handling:
- *	when UBI system couldn't be opened
- *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
- *	when UBI system couldn't create a volume
- *	- returns -PFIFLASH_ERR_UBI_MKVOL, err_buf matches text to err
- **/
-static int
-my_ubi_mkvol(int devno, int s, pfi_ubi_t u,
-	     char *err_buf, size_t err_buf_size)
-{
-	int rc, type;
-	char path[PATH_MAX];
-	libubi_t ulib;
-	struct ubi_mkvol_request req;
-
-	rc = 0;
-	ulib = NULL;
-
-	log_msg("[ ubimkvol id=%d, size=%d, data_size=%d, type=%d, "
-		"alig=%d, nlen=%d, name=%s",
-		u->ids[s], u->size, u->data_size, u->type, u->alignment,
-		strnlen(u->names[s], PFI_UBI_VOL_NAME_LEN), u->names[s]);
-
-	ulib = libubi_open();
-	if (ulib == NULL) {
-		rc = -PFIFLASH_ERR_UBI_OPEN;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	}
-
-	switch (u->type) {
-	case pfi_ubi_static:
-		type = UBI_STATIC_VOLUME; break;
-	case pfi_ubi_dynamic:
-	default:
-		type = UBI_DYNAMIC_VOLUME;
-	}
-
-	snprintf(path, PATH_MAX, DEFAULT_DEV_PATTERN, devno);
-
-	req.vol_id = u->ids[s];
-	req.alignment = u->alignment;
-	req.bytes = u->size;
-	req.vol_type = type;
-	req.name = u->names[s];
-
-	rc = ubi_mkvol(ulib, path, &req);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_UBI_MKVOL;
-		EBUF(PFIFLASH_ERRSTR[-rc], u->ids[s]);
-		goto err;
-	}
-
- err:
-	if (ulib != NULL)
-		libubi_close(ulib);
-
-	return rc;
-}
-
-
-/**
- * my_ubi_rmvol - a wrapper around the UBI library function ubi_rmvol
- * @devno	UBI device number
- * @id		UBI volume id to remove
- *
- * If the volume does not exist, the function will return success.
- *
- * Error handling:
- *	when UBI system couldn't be opened
- *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
- *	when UBI system couldn't update (truncate) a volume
- *	- returns -PFIFLASH_ERR_UBI_VOL_UPDATE, err_buf matches text to err
- *	when UBI system couldn't remove a volume
- *	- returns -PFIFLASH_ERR_UBI_RMVOL, err_buf matches text to err
- **/
-static int
-my_ubi_rmvol(int devno, uint32_t id,
-	     char *err_buf, size_t err_buf_size)
-{
-	int rc, fd;
-	char path[PATH_MAX];
-	libubi_t ulib;
-
-	rc = 0;
-	ulib = NULL;
-
-	log_msg("[ ubirmvol id=%d", id);
-
-	ulib = libubi_open();
-	if (ulib == NULL) {
-		rc = -PFIFLASH_ERR_UBI_OPEN;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	}
-
-	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
-
-	/* truncate whether it exist or not */
-	fd = open(path, O_RDWR);
-	if (fd < 0) {
-		libubi_close(ulib);
-		return 0;	/* not existent, return 0 */
-	}
-
-	rc = ubi_update_start(ulib, fd, 0);
-	close(fd);
-	if (rc < 0) {
-		rc = -PFIFLASH_ERR_UBI_VOL_UPDATE;
-		EBUF(PFIFLASH_ERRSTR[-rc], id);
-		goto err;	/* if EBUSY than empty device, continue */
-	}
-
-	snprintf(path, PATH_MAX, DEFAULT_DEV_PATTERN, devno);
-
-	rc = ubi_rmvol(ulib, path, id);
-	if (rc != 0) {
-#ifdef DEBUG
-		int rc_old = rc;
-		dbg_msg("Remove UBI volume %d returned with error: %d "
-			"errno=%d", id, rc_old, errno);
-#endif
-
-		rc = -PFIFLASH_ERR_UBI_RMVOL;
-		EBUF(PFIFLASH_ERRSTR[-rc], id);
-
-		/* TODO Define a ubi_rmvol return value which says
-		 * sth like EUBI_NOSUCHDEV. In this case, a failed
-		 * operation is acceptable. Everything else has to be
-		 * classified as real error. But talk to Andreas Arnez
-		 * before defining something odd...
-		 */
-		/* if ((errno == EINVAL) || (errno == ENODEV))
-		   return 0; */ /* currently it is EINVAL or ENODEV */
-
-		goto err;
-	}
-
- err:
-	if (ulib != NULL)
-		libubi_close(ulib);
-
-	return rc;
-}
-
-
-/**
- * read_bootenv_volume - reads the current bootenv data from id into be_old
- * @devno	UBI device number
- * @id		UBI volume id to remove
- * @bootenv_old	to hold old boot_env data
- *
- * Error handling:
- *	when UBI system couldn't be opened
- *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
- *	when UBI system couldn't open a volume to read
- *	- returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err
- *	when couldn't read bootenv data
- *	- returns -PFIFLASH_ERR_BOOTENV_READ, err_buf matches text to err
- **/
-static int
-read_bootenv_volume(int devno, uint32_t id, bootenv_t bootenv_old,
-		    char *err_buf, size_t err_buf_size)
-{
-	int rc;
-	FILE* fp_in;
-	char path[PATH_MAX];
-	libubi_t ulib;
-
-	rc = 0;
-	fp_in = NULL;
-	ulib = NULL;
-
-	ulib = libubi_open();
-	if (ulib == NULL) {
-		rc = -PFIFLASH_ERR_UBI_OPEN;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	}
-
-	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
-
-	fp_in = fopen(path, "r");
-	if (!fp_in) {
-		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
-		EBUF(PFIFLASH_ERRSTR[-rc], id);
-		goto err;
-	}
-
-	log_msg("[ reading old bootenvs ...");
-
-	/* Save old bootenvs for reference */
-	rc = bootenv_read(fp_in, bootenv_old, BOOTENV_MAXSIZE);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_READ;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	}
-
- err:
-	if (fp_in)
-		fclose(fp_in);
-	if (ulib)
-		libubi_close(ulib);
-
-	return rc;
-}
-
-
-/**
- * write_bootenv_volume - writes data from PFI file int to bootenv UBI volume
- * @devno	UBI device number
- * @id		UBI volume id
- * @bootend_old	old PDD data from machine
- * @pdd_f	function to handle PDD with
- * @fp_in	new pdd data contained in PFI
- * @fp_in_size	data size of new pdd data in PFI
- * @pfi_crc	crc value from PFI header
- *
- * Error handling:
- *	when UBI system couldn't be opened
- *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
- *	when bootenv can't be created
- *	- returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err
- *	when bootenv can't be read
- *	- returns -PFIFLASH_ERR_BOOTENV_READ, err_buf matches text to err
- *	when PDD handling function returns and error
- *	- passes rc and err_buf data
- *	when CRC check fails
- *	- returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err
- *	when bootenv can't be resized
- *	- returns -PFIFLASH_ERR_BOOTENV_SIZE, err_buf matches text to err
- *	when UBI system couldn't open a volume
- *	- returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err
- *	when couldn't write bootenv data
- *	- returns -PFIFLASH_ERR_BOOTENV_WRITE, err_buf matches text to err
- **/
-static int
-write_bootenv_volume(int devno, uint32_t id, bootenv_t bootenv_old,
-		     pdd_func_t pdd_f, FILE* fp_in, size_t fp_in_size,
-		     uint32_t pfi_crc,
-		     char *err_buf, size_t err_buf_size)
-{
-	int rc, warnings, fd_out;
-	uint32_t crc;
-	char path[PATH_MAX];
-	size_t update_size;
-	FILE *fp_out;
-	bootenv_t bootenv_new, bootenv_res;
-	libubi_t ulib;
-
-	rc = 0;
-	warnings = 0;
-	crc = 0;
-	update_size = 0;
-	fp_out = NULL;
-	bootenv_new = NULL;
-	bootenv_res = NULL;
-	ulib = NULL;
-
-	log_msg("[ ubiupdatevol bootenv id=%d, fp_in=%p", id, fp_in);
-
-	/* Workflow:
-	 * 1. Apply PDD operation and get the size of the returning
-	 *    bootenv_res section. Without the correct size it wouldn't
-	 *    be possible to call UBI update vol.
-	 * 2. Call UBI update vol
-	 * 3. Get FILE* to vol dev
-	 * 4. Write to FILE*
-	 */
-
-	ulib = libubi_open();
-	if (ulib == NULL) {
-		rc = -PFIFLASH_ERR_UBI_OPEN;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	}
-
-	rc = bootenv_create(&bootenv_new);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
-		EBUF(PFIFLASH_ERRSTR[-rc], " 'new'");
-		goto err;
-	}
-
-	rc = bootenv_create(&bootenv_res);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
-		EBUF(PFIFLASH_ERRSTR[-rc], " 'res'");
-		goto err;
-	}
-
-	rc = bootenv_read_crc(fp_in, bootenv_new, fp_in_size, &crc);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_READ;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	} else if (crc != pfi_crc) {
-		rc = -PFIFLASH_ERR_CRC_CHECK;
-		EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc);
-		goto err;
-	}
-
-	rc = pdd_f(bootenv_old, bootenv_new, &bootenv_res, &warnings,
-		   err_buf, err_buf_size);
-	if (rc != 0) {
-		EBUF_PREPEND("handling PDD");
-		goto err;
-	}
-	else if (warnings)
-		/* TODO do something with warnings */
-		dbg_msg("A warning in the PDD operation occured: %d",
-			warnings);
-
-	rc = bootenv_size(bootenv_res, &update_size);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_SIZE;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	}
-
-	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
-
-	fd_out = open(path, O_RDWR);
-	if (fd_out < 0) {
-		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
-		EBUF(PFIFLASH_ERRSTR[-rc], id);
-		goto err;
-	}
-	fp_out = fdopen(fd_out, "r+");
-	if (!fp_out) {
-		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
-		EBUF(PFIFLASH_ERRSTR[-rc], id);
-		goto err;
-	}
-	rc = ubi_update_start(ulib, fd_out, update_size);
-	if (rc < 0) {
-		rc = -PFIFLASH_ERR_UBI_VOL_UPDATE;
-		EBUF(PFIFLASH_ERRSTR[-rc], id);
-		goto err;
-	}
-
-	rc = bootenv_write(fp_out, bootenv_res);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_WRITE;
-		EBUF(PFIFLASH_ERRSTR[-rc], devno, id);
-		goto err;
-	}
-
- err:
-	if (ulib != NULL)
-		libubi_close(ulib);
-	if (bootenv_new != NULL)
-		bootenv_destroy(&bootenv_new);
-	if (bootenv_res != NULL)
-		bootenv_destroy(&bootenv_res);
-	if (fp_out)
-		fclose(fp_out);
-
-	return rc;
-}
-
-
-/**
- * write_normal_volume - writes data from PFI file int to regular UBI volume
- * @devno	UBI device number
- * @id		UBI volume id
- * @update_size	size of data stream
- * @fp_in	PFI data file pointer
- * @pfi_crc	CRC data from PFI header
- *
- * Error handling:
- *	when UBI system couldn't be opened
- *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
- *	when UBI system couldn't open a volume
- *	- returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err
- *	when unexpected EOF is encountered
- *	- returns -PFIFLASH_ERR_EOF, err_buf matches text to err
- *	when file I/O error
- *	- returns -PFIFLASH_ERR_FIO, err_buf matches text to err
- *	when CRC check fails
- *	- retruns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err
- **/
-static int
-write_normal_volume(int devno, uint32_t id, size_t update_size, FILE* fp_in,
-		    uint32_t pfi_crc,
-		    char *err_buf, size_t err_buf_size)
-{
-	int rc, fd_out;
-	uint32_t crc, crc32_table[256];
-	char path[PATH_MAX];
-	size_t bytes_left;
-	FILE* fp_out;
-	libubi_t ulib;
-
-	rc = 0;
-	crc = UBI_CRC32_INIT;
-	bytes_left = update_size;
-	fp_out = NULL;
-	ulib = NULL;
-
-	log_msg("[ ubiupdatevol id=%d, update_size=%d fp_in=%p",
-		id, update_size, fp_in);
-
-	ulib = libubi_open();
-	if (ulib == NULL) {
-		rc = -PFIFLASH_ERR_UBI_OPEN;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	}
-
-	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
-
-	fd_out = open(path, O_RDWR);
-	if (fd_out < 0) {
-		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
-		EBUF(PFIFLASH_ERRSTR[-rc], id);
-		goto err;
-	}
-	fp_out = fdopen(fd_out, "r+");
-	if (!fp_out) {
-		rc = -PFIFLASH_ERR_UBI_VOL_FOPEN;
-		EBUF(PFIFLASH_ERRSTR[-rc], id);
-		goto err;
-	}
-	rc = ubi_update_start(ulib, fd_out, update_size);
-	if (rc < 0) {
-		rc = -PFIFLASH_ERR_UBI_VOL_UPDATE;
-		EBUF(PFIFLASH_ERRSTR[-rc], id);
-		goto err;
-	}
-
-	init_crc32_table(crc32_table);
-	while (bytes_left) {
-		char buf[1024];
-		size_t to_rw = sizeof buf > bytes_left ?
-			bytes_left : sizeof buf;
-		if (fread(buf, 1, to_rw, fp_in) != to_rw) {
-			rc = -PFIFLASH_ERR_EOF;
-			EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-			goto err;
-		}
-		crc = clc_crc32(crc32_table, crc, buf, to_rw);
-		if (fwrite(buf, 1, to_rw, fp_out) != to_rw) {
-			rc = -PFIFLASH_ERR_FIO;
-			EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-			goto err;
-		}
-		bytes_left -= to_rw;
-	}
-
-	if (crc != pfi_crc) {
-		rc = -PFIFLASH_ERR_CRC_CHECK;
-		EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc);
-		goto err;
-	}
-
- err:
-	if (fp_out)
-		fclose(fp_out);
-	if (ulib)
-		libubi_close(ulib);
-
-	return rc;
-}
-
-static int compare_bootenv(FILE *fp_pfi, FILE **fp_flash, uint32_t ids_size,
-		uint32_t data_size, pdd_func_t pdd_f, char *err_buf,
-		size_t err_buf_size)
-{
-	int rc, warnings = 0;
-	unsigned int i;
-	bootenv_t bootenv_pfi, bootenv_res = NULL, bootenv_flash = NULL;
-
-	rc = bootenv_create(&bootenv_pfi);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
-		goto err;
-	}
-
-	rc = bootenv_create(&bootenv_res);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
-		goto err;
-	}
-
-	rc = bootenv_read(fp_pfi, bootenv_pfi, data_size);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_READ;
-		goto err;
-	}
-
-	for (i = 0; i < ids_size; i++) {
-		rc = bootenv_create(&bootenv_flash);
-		if (rc != 0) {
-			rc = -PFIFLASH_ERR_BOOTENV_CREATE;
-			goto err;
-		}
-
-		rc = bootenv_read(fp_flash[i], bootenv_flash, BOOTENV_MAXSIZE);
-		if (rc != 0) {
-			rc = -PFIFLASH_ERR_BOOTENV_READ;
-			goto err;
-		}
-
-		rc = pdd_f(bootenv_flash, bootenv_pfi, &bootenv_res,
-				&warnings, err_buf, err_buf_size);
-		if (rc != 0) {
-			rc = -PFIFLASH_ERR_PDD_UNKNOWN;
-			goto err;
-		}
-
-		rc = bootenv_compare(bootenv_flash, bootenv_res);
-		if (rc > 0) {
-			rc = -PFIFLASH_CMP_DIFF;
-			goto err;
-		} else if (rc < 0) {
-			rc = -PFIFLASH_ERR_COMPARE;
-			goto err;
-		}
-
-		bootenv_destroy(&bootenv_flash);
-		bootenv_flash = NULL;
-	}
-
-err:
-	if (bootenv_pfi)
-		bootenv_destroy(&bootenv_pfi);
-	if (bootenv_res)
-		bootenv_destroy(&bootenv_res);
-	if (bootenv_flash)
-		bootenv_destroy(&bootenv_flash);
-
-	return rc;
-}
-
-static int compare_data(FILE *fp_pfi, FILE **fp_flash, uint32_t ids_size,
-		uint32_t bytes_left)
-{
-	unsigned int i;
-	size_t read_bytes, rc = 0;
-	char buf_pfi[COMPARE_BUFFER_SIZE];
-	char *buf_flash[ids_size];
-
-	for (i = 0; i < ids_size; i++) {
-		buf_flash[i] = malloc(COMPARE_BUFFER_SIZE);
-		if (!buf_flash[i])
-			return -PFIFLASH_ERR_COMPARE;
-	}
-
-	while (bytes_left) {
-		if (bytes_left > COMPARE_BUFFER_SIZE)
-			read_bytes = COMPARE_BUFFER_SIZE;
-		else
-			read_bytes = bytes_left;
-
-		rc = fread(buf_pfi, 1, read_bytes, fp_pfi);
-		if (rc != read_bytes) {
-			rc = -PFIFLASH_ERR_COMPARE;
-			goto err;
-		}
-
-		for (i = 0; i < ids_size; i++) {
-			rc = fread(buf_flash[i], 1, read_bytes, fp_flash[i]);
-			if (rc != read_bytes) {
-				rc = -PFIFLASH_CMP_DIFF;
-				goto err;
-			}
-
-			rc = memcmp(buf_pfi, buf_flash[i], read_bytes);
-			if (rc != 0) {
-				rc = -PFIFLASH_CMP_DIFF;
-				goto err;
-			}
-		}
-
-		bytes_left -= read_bytes;
-	}
-
-err:
-	for (i = 0; i < ids_size; i++)
-		free(buf_flash[i]);
-
-	return rc;
-}
-
-static int compare_volumes(int devno, pfi_ubi_t u, FILE *fp_pfi,
-		pdd_func_t pdd_f, char *err_buf, size_t err_buf_size)
-{
-	int rc, is_bootenv = 0;
-	unsigned int i;
-	char path[PATH_MAX];
-	libubi_t ulib = NULL;
-	FILE *fp_flash[u->ids_size];
-
-	ulib = libubi_open();
-	if (ulib == NULL) {
-		rc = -PFIFLASH_ERR_UBI_OPEN;
-		goto err;
-	}
-
-	for (i = 0; i < u->ids_size; i++) {
-		if (u->ids[i] == EXAMPLE_BOOTENV_VOL_ID_1 ||
-		    u->ids[i] == EXAMPLE_BOOTENV_VOL_ID_2)
-			is_bootenv = 1;
-
-		snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, u->ids[i]);
-
-		fp_flash[i] = fopen(path, "r");
-		if (fp_flash[i] == NULL) {
-			rc = -PFIFLASH_ERR_UBI_OPEN;
-			goto err;
-		}
-	}
-
-	if (is_bootenv)
-		rc = compare_bootenv(fp_pfi, fp_flash, u->ids_size,
-				u->data_size, pdd_f, err_buf, err_buf_size);
-	else
-		rc = compare_data(fp_pfi, fp_flash, u->ids_size, u->data_size);
-
-err:
-	if (rc < 0)
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-
-	for (i = 0; i < u->ids_size; i++)
-		fclose(fp_flash[i]);
-	if (ulib)
-		libubi_close(ulib);
-
-	return rc;
-}
-
-static int
-erase_mtd_region(FILE* file_p, int start, int length)
-{
-	int rc, fd;
-	erase_info_t erase;
-	mtd_info_t mtdinfo;
-	loff_t offset = start;
-	loff_t end = offset + length;
-
-	fd = fileno(file_p);
-	if (fd < 0)
-		return -PFIFLASH_ERR_MTD_ERASE;
-
-	rc = ioctl(fd, MEMGETINFO, &mtdinfo);
-	if (rc)
-		return -PFIFLASH_ERR_MTD_ERASE;
-
-	/* check for bad blocks in case of NAND flash */
-	if (mtdinfo.type == MTD_NANDFLASH) {
-		while (offset < end) {
-			rc = ioctl(fd, MEMGETBADBLOCK, &offset);
-			if (rc > 0) {
-				return -PFIFLASH_ERR_MTD_ERASE;
-			}
-
-			offset += mtdinfo.erasesize;
-		}
-	}
-
-	erase.start = start;
-	erase.length = length;
-
-	rc = ioctl(fd, MEMERASE, &erase);
-	if (rc) {
-		return -PFIFLASH_ERR_MTD_ERASE;
-	}
-
-	return rc;
-}
-
-/**
- * process_raw_volumes - writes the raw sections of the PFI data
- * @pfi		PFI data file pointer
- * @pfi_raws	list of PFI raw headers
- * @rawdev	device to use to write raw data
- *
- * Error handling:
- *	when early EOF in PFI data
- *	- returns -PFIFLASH_ERR_EOF, err_buf matches text to err
- *	when file I/O error
- *	- returns -PFIFLASH_ERR_FIO, err_buf matches text to err
- *	when CRC check fails
- *	- returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err
- *	when opening MTD device fails
- *	- reutrns -PFIFLASH_ERR_MTD_OPEN, err_buf matches text to err
- *	when closing MTD device fails
- *	- returns -PFIFLASH_ERR_MTD_CLOSE, err_buf matches text to err
- **/
-static int
-process_raw_volumes(FILE* pfi, list_t pfi_raws, const char* rawdev,
-		    char* err_buf, size_t err_buf_size)
-{
-	int rc;
-	char *pfi_data;
-	void *i;
-	uint32_t crc, crc32_table[256];
-	size_t j, k;
-	FILE* mtd = NULL;
-	list_t ptr;
-
-	if (is_empty(pfi_raws))
-		return 0;
-
-	if (rawdev == NULL)
-		return 0;
-
-	rc = 0;
-
-	pfi_data = NULL;
-
-	log_msg("[ rawupdate dev=%s", rawdev);
-
-	crc = UBI_CRC32_INIT;
-	init_crc32_table(crc32_table);
-
-	/* most likely only one element in list, but just in case */
-	foreach(i, ptr, pfi_raws) {
-		pfi_raw_t r = (pfi_raw_t)i;
-
-		/* read in pfi data */
-		if (pfi_data != NULL)
-			free(pfi_data);
-		pfi_data = malloc(r->data_size * sizeof(char));
-		for (j = 0; j < r->data_size; j++) {
-			int c = fgetc(pfi);
-			if (c == EOF) {
-				rc = -PFIFLASH_ERR_EOF;
-				EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-				goto err;
-			} else if (ferror(pfi)) {
-				rc = -PFIFLASH_ERR_FIO;
-				EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-				goto err;
-			}
-			pfi_data[j] = (char)c;
-		}
-		crc = clc_crc32(crc32_table, crc, pfi_data, r->data_size);
-
-		/* check crc */
-		if (crc != r->crc) {
-			rc = -PFIFLASH_ERR_CRC_CHECK;
-			EBUF(PFIFLASH_ERRSTR[-rc], r->crc, crc);
-			goto err;
-		}
-
-		/* open device */
-		mtd = fopen(rawdev, "r+");
-		if (mtd == NULL) {
-			rc = -PFIFLASH_ERR_MTD_OPEN;
-			EBUF(PFIFLASH_ERRSTR[-rc], rawdev);
-			goto err;
-		}
-
-		for (j = 0; j < r->starts_size; j++) {
-			rc = erase_mtd_region(mtd, r->starts[j], r->data_size);
-			if (rc) {
-				EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-				goto err;
-			}
-
-			fseek(mtd, r->starts[j], SEEK_SET);
-			for (k = 0; k < r->data_size; k++) {
-				int c = fputc((int)pfi_data[k], mtd);
-				if (c == EOF) {
-					fclose(mtd);
-					rc = -PFIFLASH_ERR_EOF;
-					EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-					goto err;
-				}
-				if ((char)c != pfi_data[k]) {
-					fclose(mtd);
-					rc = -1;
-					goto err;
-				}
-			}
-		}
-		rc = fclose(mtd);
-		mtd = NULL;
-		if (rc != 0) {
-			rc = -PFIFLASH_ERR_MTD_CLOSE;
-			EBUF(PFIFLASH_ERRSTR[-rc], rawdev);
-			goto err;
-		}
-	}
-
- err:
-	if (mtd != NULL)
-		fclose(mtd);
-	if (pfi_data != NULL)
-		free(pfi_data);
-	return rc;
-}
-
-
-/**
- * erase_unmapped_ubi_volumes - skip volumes provided by PFI file, clear rest
- * @devno	UBI device number
- * @pfi_ubis	list of UBI header data
- *
- * Error handling:
- *	when UBI id is out of bounds
- *	- returns -PFIFLASH_ERR_UBI_VID_OOB, err_buf matches text to err
- *	when UBI volume can't be removed
- *	- passes rc, prepends err_buf with contextual aid
- **/
-static int
-erase_unmapped_ubi_volumes(int devno, list_t pfi_ubis,
-			   char *err_buf, size_t err_buf_size)
-{
-	int rc;
-	uint8_t ubi_volumes[PFI_UBI_MAX_VOLUMES];
-	size_t i;
-	list_t ptr;
-	pfi_ubi_t u;
-
-	rc = 0;
-
-	for (i = 0; i < PFI_UBI_MAX_VOLUMES; i++)
-		ubi_volumes[i] = 1;
-
-	foreach(u, ptr, pfi_ubis) {
-		/* iterate over each vol_id */
-		for(i = 0; i < u->ids_size; i++) {
-			if (u->ids[i] >= PFI_UBI_MAX_VOLUMES) {
-				rc = -PFIFLASH_ERR_UBI_VID_OOB;
-				EBUF(PFIFLASH_ERRSTR[-rc], u->ids[i]);
-				goto err;
-			}
-			/* remove from removal list */
-			ubi_volumes[u->ids[i]] = 0;
-		}
-	}
-
-	for (i = 0; i < PFI_UBI_MAX_VOLUMES; i++) {
-		if (ubi_volumes[i]) {
-			rc = my_ubi_rmvol(devno, i, err_buf, err_buf_size);
-			if (rc != 0) {
-				EBUF_PREPEND("remove volume failed");
-				goto err;
-			}
-		}
-	}
-
- err:
-	return rc;
-}
-
-
-/**
- * process_ubi_volumes - delegate tasks regarding UBI volumes
- * @pfi			PFI data file pointer
- * @seqnum		sequence number
- * @pfi_ubis		list of UBI header data
- * @bootenv_old		storage for current system PDD
- * @pdd_f		function to handle PDD
- * @ubi_update_process	whether reading or writing
- *
- * Error handling:
- *	when and unknown ubi_update_process is given
- *	- returns -PFIFLASH_ERR_UBI_UNKNOWN, err_buf matches text to err
- *	otherwise
- *	- passes rc and err_buf
- **/
-static int
-process_ubi_volumes(FILE* pfi, int seqnum, list_t pfi_ubis,
-		    bootenv_t bootenv_old, pdd_func_t pdd_f,
-		    ubi_update_process_t ubi_update_process,
-		    char *err_buf, size_t err_buf_size)
-{
-	int rc;
-	pfi_ubi_t u;
-	list_t ptr;
-
-	rc = 0;
-
-	foreach(u, ptr, pfi_ubis) {
-		int s = seqnum;
-
-		if (s > ((int)u->ids_size - 1))
-			s = 0; /* per default use the first */
-		u->curr_seqnum = s;
-
-		switch (ubi_update_process) {
-		case UBI_REMOVE:
-			/* TODO are all these "EXAMPLE" vars okay? */
-			if ((u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_1) ||
-			    (u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_2)) {
-				rc = read_bootenv_volume(EXAMPLE_UBI_DEVICE,
-							 u->ids[s], bootenv_old,
-							 err_buf, err_buf_size);
-				/* it's okay if there is no bootenv
-				 * we're going to write one */
-				if ((rc == -PFIFLASH_ERR_UBI_VOL_FOPEN) ||
-				    (rc == -PFIFLASH_ERR_BOOTENV_READ))
-					rc = 0;
-				if (rc != 0)
-					goto err;
-			}
-
-			rc = my_ubi_rmvol(EXAMPLE_UBI_DEVICE, u->ids[s],
-					  err_buf, err_buf_size);
-			if (rc != 0)
-				goto err;
-
-			break;
-		case UBI_WRITE:
-			rc = my_ubi_mkvol(EXAMPLE_UBI_DEVICE, s, u,
-					  err_buf, err_buf_size);
-			if (rc != 0) {
-				EBUF_PREPEND("creating volume");
-				goto err;
-			}
-
-			if ((u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_1) ||
-			    (u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_2)) {
-				rc = write_bootenv_volume(EXAMPLE_UBI_DEVICE,
-							  u->ids[s],
-							  bootenv_old, pdd_f,
-							  pfi,
-							  u->data_size,
-							  u->crc,
-							  err_buf,
-							  err_buf_size);
-				if (rc != 0)
-					EBUF_PREPEND("bootenv volume");
-			} else {
-				rc = write_normal_volume(EXAMPLE_UBI_DEVICE,
-							 u->ids[s],
-							 u->data_size, pfi,
-							 u->crc,
-							 err_buf,
-							 err_buf_size);
-				if (rc != 0)
-					EBUF_PREPEND("normal volume");
-			}
-			if (rc != 0)
-				goto err;
-
-			break;
-		case UBI_COMPARE:
-			rc = compare_volumes(EXAMPLE_UBI_DEVICE, u, pfi, pdd_f,
-					err_buf, err_buf_size);
-			if (rc != 0) {
-				EBUF_PREPEND("compare volume");
-				goto err;
-			}
-
-			break;
-		default:
-			rc = -PFIFLASH_ERR_UBI_UNKNOWN;
-			EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-			goto err;
-		}
-	}
-
- err:
-	return rc;
-}
-
-
-/**
- * mirror_ubi_volumes - mirror redundant pairs of volumes
- * @devno	UBI device number
- * @pfi_ubis	list of PFI header data
- *
- * Error handling:
- *	when UBI system couldn't be opened
- *	- returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err
- **/
-static int
-mirror_ubi_volumes(uint32_t devno, list_t pfi_ubis,
-		   char *err_buf, size_t err_buf_size)
-{
-	int rc;
-	uint32_t j;
-	list_t ptr;
-	pfi_ubi_t i;
-	libubi_t ulib;
-
-	rc = 0;
-	ulib = NULL;
-
-	log_msg("[ mirror ...");
-
-	ulib = libubi_open();
-	if (ulib == NULL) {
-		rc = -PFIFLASH_ERR_UBI_OPEN;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	}
-
-	/**
-	 * Execute all mirror operations on redundant groups.
-	 * Create a volume within a redundant group if it does
-	 * not exist already (this is a precondition of
-	 * ubimirror).
-	 */
-	foreach(i, ptr, pfi_ubis) {
-		for (j = 0; j < i->ids_size; j++) {
-			/* skip self-match */
-			if (i->ids[j] == i->ids[i->curr_seqnum])
-				continue;
-
-			rc = my_ubi_rmvol(devno, i->ids[j],
-					  err_buf, err_buf_size);
-			if (rc != 0)
-				goto err;
-
-			rc = my_ubi_mkvol(devno, j, i,
-					  err_buf, err_buf_size);
-			if (rc != 0)
-				goto err;
-		}
-	}
-
-	foreach(i, ptr, pfi_ubis) {
-		rc = ubimirror(devno, i->curr_seqnum, i->ids, i->ids_size,
-			       err_buf, err_buf_size);
-		if (rc != 0)
-			goto err;
-	}
-
-
- err:
-	if (ulib != NULL)
-		libubi_close(ulib);
-
-	return rc;
-}
-
-
-/**
- * pfiflash_with_options - exposed func to flash memory with a PFI file
- * @pfi			PFI data file pointer
- * @complete		flag to erase unmapped volumes
- * @seqnum		sequence number
- * @compare		flag to compare
- * @pdd_handling	method to handle pdd (keep, merge, overwrite...)
- *
- * Error handling:
- *	when bootenv can't be created
- *	- returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err
- *	when PFI headers can't be read, or
- *	when fail to skip raw sections, or
- *	when error occurs while processing raw volumes, or
- *	when fail to erase unmapped UBI vols, or
- *	when error occurs while processing UBI volumes, or
- *	when error occurs while mirroring UBI volumes
- *	- passes rc, prepends err_buf with contextual aid
- **/
-int
-pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare,
-		  pdd_handling_t pdd_handling, const char* rawdev,
-		  char *err_buf, size_t err_buf_size)
-{
-	int rc;
-	bootenv_t bootenv;
-	pdd_func_t pdd_f;
-
-	if (pfi == NULL)
-		return -EINVAL;
-
-	rc = 0;
-	pdd_f = NULL;
-
-	/* If the user didnt specify a seqnum we start per default
-	 * with the index 0 */
-	int curr_seqnum = seqnum < 0 ? 0 : seqnum;
-
-	list_t pfi_raws   = mk_empty(); /* list of raw sections from a pfi */
-	list_t pfi_ubis   = mk_empty(); /* list of ubi sections from a pfi */
-
-	rc = bootenv_create(&bootenv);
-	if (rc != 0) {
-		rc = -PFIFLASH_ERR_BOOTENV_CREATE;
-		EBUF(PFIFLASH_ERRSTR[-rc], "");
-		goto err;
-	}
-
-	rc = read_pfi_headers(&pfi_raws, &pfi_ubis, pfi, err_buf, err_buf_size);
-	if (rc != 0) {
-		EBUF_PREPEND("reading PFI header");
-		goto err;
-	}
-
-	if (rawdev == NULL || compare)
-		rc = skip_raw_volumes(pfi, pfi_raws, err_buf, err_buf_size);
-	else
-		rc = process_raw_volumes(pfi, pfi_raws, rawdev, err_buf,
-					 err_buf_size);
-	if (rc != 0) {
-		EBUF_PREPEND("handling raw section");
-		goto err;
-	}
-
-	if (complete && !compare) {
-		rc = erase_unmapped_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis,
-						err_buf, err_buf_size);
-		if (rc != 0) {
-			EBUF_PREPEND("deleting unmapped UBI volumes");
-			goto err;
-		}
-	}
-
-	if (((int)pdd_handling >= 0) &&
-	    (pdd_handling < PDD_HANDLING_NUM))
-		pdd_f = pdd_funcs[pdd_handling];
-	else {
-		rc = -PFIFLASH_ERR_PDD_UNKNOWN;
-		EBUF("%s", PFIFLASH_ERRSTR[-rc]);
-		goto err;
-	}
-
-	if (!compare) {
-		rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv,
-				pdd_f, UBI_REMOVE, err_buf, err_buf_size);
-		if (rc != 0) {
-			EBUF_PREPEND("removing UBI volumes");
-			goto err;
-		}
-
-		rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv,
-				pdd_f, UBI_WRITE, err_buf, err_buf_size);
-		if  (rc != 0) {
-			EBUF_PREPEND("writing UBI volumes");
-			goto err;
-		}
-
-		if (seqnum < 0) { /* mirror redundant pairs */
-			rc = mirror_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis,
-					err_buf, err_buf_size);
-			if (rc != 0) {
-				EBUF_PREPEND("mirroring UBI volumes");
-				goto err;
-			}
-		}
-	} else {
-		/* only compare volumes, don't alter the content */
-		rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv,
-				pdd_f, UBI_COMPARE, err_buf, err_buf_size);
-
-		if (rc == -PFIFLASH_CMP_DIFF)
-			/* update is necessary, return positive value */
-			rc = 1;
-
-		if (rc < 0) {
-			EBUF_PREPEND("comparing UBI volumes");
-			goto err;
-		}
-	}
-
- err:
-	pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws);
-	pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis);
-	bootenv_destroy(&bootenv);
-	return rc;
-}
-
-
-/**
- * pfiflash - passes to pfiflash_with_options
- * @pfi			PFI data file pointer
- * @complete		flag to erase unmapped volumes
- * @seqnum		sequence number
- * @pdd_handling	method to handle pdd (keep, merge, overwrite...)
- **/
-int
-pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling,
-		char *err_buf, size_t err_buf_size)
-{
-	return pfiflash_with_options(pfi, complete, seqnum, 0, pdd_handling,
-				 NULL, err_buf, err_buf_size);
-}
diff --git a/ubi-utils/src/libscan.c b/ubi-utils/src/libscan.c
new file mode 100644
index 0000000..dc1f083
--- /dev/null
+++ b/ubi-utils/src/libscan.c
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * UBI scanning library.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <mtd_swab.h>
+#include <mtd/ubi-media.h>
+#include <mtd/mtd-user.h>
+#include <libmtd.h>
+#include <libscan.h>
+#include "common.h"
+#include "crc32.h"
+
+#define PROGRAM_NAME "libscan"
+
+static int all_ff(const void *buf, int len)
+{
+	int i;
+	const uint8_t *p = buf;
+
+	for (i = 0; i < len; i++)
+		if (p[i] != 0xFF)
+			return 0;
+	return 1;
+}
+
+int ubi_scan(struct mtd_info *mtd, struct ubi_scan_info **info, int verbose)
+{
+	int eb, v = (verbose == 2), pr = (verbose == 1);
+	struct ubi_scan_info *si;
+	unsigned long long sum = 0;
+
+	si = calloc(1, sizeof(struct ubi_scan_info));
+	if (!si)
+		return sys_errmsg("cannot allocate %zd bytes of memory",
+				  sizeof(struct ubi_scan_info));
+
+	si->ec = calloc(mtd->eb_cnt, sizeof(uint32_t));
+	if (!si->ec) {
+		sys_errmsg("cannot allocate %zd bytes of memory",
+			   sizeof(struct ubi_scan_info));
+		goto out_si;
+	}
+
+	si->vid_hdr_offs = si->data_offs = -1;
+
+	verbose(v, "start scanning eraseblocks 0-%d", mtd->eb_cnt);
+	for (eb = 0; eb < mtd->eb_cnt; eb++) {
+		int ret;
+		uint32_t crc;
+		struct ubi_ec_hdr hdr;
+		unsigned long long ec;
+
+		if (v) {
+			normsg_cont("scanning eraseblock %d", eb);
+			fflush(stdout);
+		}
+		if (pr) {
+			printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2lld %% complete  ",
+			       eb, (long long)(eb + 1) * 100 / mtd->eb_cnt);
+			fflush(stdout);
+		}
+
+		ret = mtd_is_bad(mtd, eb);
+		if (ret == -1)
+			goto out_ec;
+		if (ret) {
+			si->bad_cnt += 1;
+			si->ec[eb] = EB_BAD;
+			if (v)
+				printf(": bad\n");
+			continue;
+		}
+
+		ret = mtd_read(mtd, eb, 0, &hdr, sizeof(struct ubi_ec_hdr));;
+		if (ret < 0)
+			goto out_ec;
+
+		/* Check the EC header */
+		if (be32_to_cpu(hdr.magic) != UBI_EC_HDR_MAGIC) {
+			if (all_ff(&hdr, sizeof(struct ubi_ec_hdr))) {
+				si->empty_cnt += 1;
+				si->ec[eb] = EB_EMPTY;
+				if (v)
+					printf(": empty\n");
+			} else {
+				si->alien_cnt += 1;
+				si->ec[eb] = EB_ALIEN;
+				if (v)
+					printf(": alien\n");
+			}
+			continue;
+		}
+
+		crc = crc32(UBI_CRC32_INIT, &hdr, UBI_EC_HDR_SIZE_CRC);
+		if (be32_to_cpu(hdr.hdr_crc) != crc) {
+			si->corrupted_cnt += 1;
+			si->ec[eb] = EB_CORRUPTED;
+			if (v)
+				printf(": bad CRC %#08x, should be %#08x\n",
+				       crc, be32_to_cpu(hdr.hdr_crc));
+			continue;
+		}
+
+		ec = be64_to_cpu(hdr.ec);
+		if (ec > EC_MAX) {
+			if (pr)
+				printf("\n");
+			errmsg("erase counter in EB %d is %llu, while this "
+			       "program expects them to be less than %u",
+			       eb, ec, EC_MAX);
+			goto out_ec;
+		}
+
+		if (si->vid_hdr_offs == -1) {
+			si->vid_hdr_offs = be32_to_cpu(hdr.vid_hdr_offset);
+			si->data_offs = be32_to_cpu(hdr.data_offset);
+			if (si->data_offs % mtd->min_io_size) {
+				if (pr)
+					printf("\n");
+				if (v)
+					printf(": corrupted because of the below\n");
+				warnmsg("bad data offset %d at eraseblock %d (n"
+					"of multiple of min. I/O unit size %d)",
+					si->data_offs, eb, mtd->min_io_size);
+				warnmsg("treat eraseblock %d as corrupted", eb);
+				si->corrupted_cnt += 1;
+				si->ec[eb] = EB_CORRUPTED;
+				continue;
+
+			}
+		} else {
+			if ((int)be32_to_cpu(hdr.vid_hdr_offset) != si->vid_hdr_offs) {
+				if (pr)
+					printf("\n");
+				if (v)
+					printf(": corrupted because of the below\n");
+				warnmsg("inconsistent VID header offset: was "
+					"%d, but is %d in eraseblock %d",
+					si->vid_hdr_offs,
+					be32_to_cpu(hdr.vid_hdr_offset), eb);
+				warnmsg("treat eraseblock %d as corrupted", eb);
+				si->corrupted_cnt += 1;
+				si->ec[eb] = EB_CORRUPTED;
+				continue;
+			}
+			if ((int)be32_to_cpu(hdr.data_offset) != si->data_offs) {
+				if (pr)
+					printf("\n");
+				if (v)
+					printf(": corrupted because of the below\n");
+				warnmsg("inconsistent data offset: was %d, but"
+					" is %d in eraseblock %d",
+					si->data_offs,
+					be32_to_cpu(hdr.data_offset), eb);
+				warnmsg("treat eraseblock %d as corrupted", eb);
+				si->corrupted_cnt += 1;
+				si->ec[eb] = EB_CORRUPTED;
+				continue;
+			}
+		}
+
+		si->ok_cnt += 1;
+		si->ec[eb] = ec;
+		if (v)
+			printf(": OK, erase counter %u\n", si->ec[eb]);
+	}
+
+	if (si->ok_cnt != 0) {
+		/* Calculate mean erase counter */
+		for (eb = 0; eb < mtd->eb_cnt; eb++) {
+			if (si->ec[eb] > EC_MAX)
+				continue;
+			sum += si->ec[eb];
+		}
+		si->mean_ec = sum / si->ok_cnt;
+	}
+
+	si->good_cnt = mtd->eb_cnt - si->bad_cnt;
+	verbose(v, "finished, mean EC %lld, %d OK, %d corrupted, %d empty, %d "
+		"alien, bad %d", si->mean_ec, si->ok_cnt, si->corrupted_cnt,
+		si->empty_cnt, si->alien_cnt, si->bad_cnt);
+
+	*info = si;
+	if (pr)
+		printf("\n");
+	return 0;
+
+out_ec:
+	free(si->ec);
+out_si:
+	free(si);
+	*info = NULL;
+	return -1;
+}
+
+void ubi_scan_free(struct ubi_scan_info *si)
+{
+	free(si->ec);
+	free(si);
+}
diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c
index a536b47..1aa66d8 100644
--- a/ubi-utils/src/libubi.c
+++ b/ubi-utils/src/libubi.c
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Author: Artem B. Bityutskiy
+ * Author: Artem Bityutskiy
  *
  * UBI (Unsorted Block Images) library.
  */
@@ -27,14 +27,487 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <dirent.h>
-#include <errno.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <limits.h>
 #include "libubi.h"
 #include "libubi_int.h"
+#include "common.h"
 
-libubi_t libubi_open(void)
+#define PROGRAM_NAME "libubi"
+
+/**
+ * mkpath - compose full path from 2 given components.
+ * @path: the first component
+ * @name: the second component
+ *
+ * This function returns the resulting path in case of success and %NULL in
+ * case of failure.
+ */
+static char *mkpath(const char *path, const char *name)
+{
+	char *n;
+	int len1 = strlen(path);
+	int len2 = strlen(name);
+
+	n = malloc(len1 + len2 + 2);
+	if (!n) {
+		sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2);
+		return NULL;
+	}
+
+	memcpy(n, path, len1);
+	if (n[len1 - 1] != '/')
+		n[len1++] = '/';
+
+	memcpy(n + len1, name, len2 + 1);
+	return n;
+}
+
+/**
+ * read_positive_ll - read a positive 'long long' value from a file.
+ * @file: the file to read from
+ * @value: the result is stored here
+ *
+ * This function reads file @file and interprets its contents as a positive
+ * 'long long' integer. If this is not true, it fails with %EINVAL error code.
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+static int read_positive_ll(const char *file, long long *value)
+{
+	int fd, rd;
+	char buf[50];
+
+	fd = open(file, O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, buf, 50);
+	if (rd == -1) {
+		sys_errmsg("cannot read \"%s\"", file);
+		goto out_error;
+	}
+	if (rd == 50) {
+		errmsg("contents of \"%s\" is too long", file);
+		errno = EINVAL;
+		goto out_error;
+	}
+
+	if (sscanf(buf, "%lld\n", value) != 1) {
+		/* This must be a UBI bug */
+		errmsg("cannot read integer from \"%s\"\n", file);
+		errno = EINVAL;
+		goto out_error;
+	}
+
+	if (*value < 0) {
+		errmsg("negative value %lld in \"%s\"", *value, file);
+		errno = EINVAL;
+		goto out_error;
+	}
+
+	if (close(fd))
+		return sys_errmsg("close failed on \"%s\"", file);
+
+	return 0;
+
+out_error:
+	close(fd);
+	return -1;
+}
+
+/**
+ * read_positive_int - read a positive 'int' value from a file.
+ * @file: the file to read from
+ * @value: the result is stored here
+ *
+ * This function is the same as 'read_positive_ll()', but it reads an 'int'
+ * value, not 'long long'.
+ */
+static int read_positive_int(const char *file, int *value)
+{
+	long long res;
+
+	if (read_positive_ll(file, &res))
+		return -1;
+
+	/* Make sure the value is not too big */
+	if (res > INT_MAX) {
+		errmsg("value %lld read from file \"%s\" is out of range",
+		       res, file);
+		errno = EINVAL;
+		return -1;
+	}
+
+	*value = res;
+	return 0;
+}
+
+/**
+ * read_data - read data from a file.
+ * @file: the file to read from
+ * @buf: the buffer to read to
+ * @buf_len: buffer length
+ *
+ * This function returns number of read bytes in case of success and %-1 in
+ * case of failure. Note, if the file contains more then @buf_len bytes of
+ * date, this function fails with %EINVAL error code.
+ */
+static int read_data(const char *file, void *buf, int buf_len)
+{
+	int fd, rd, tmp, tmp1;
+
+	fd = open(file, O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, buf, buf_len);
+	if (rd == -1) {
+		sys_errmsg("cannot read \"%s\"", file);
+		goto out_error;
+	}
+
+	/* Make sure all data is read */
+	tmp1 = read(fd, &tmp, 1);
+	if (tmp1 == 1) {
+		sys_errmsg("cannot read \"%s\"", file);
+		goto out_error;
+	}
+	if (tmp1) {
+		errmsg("file \"%s\" contains too much data (> %d bytes)",
+		       file, buf_len);
+		errno = EINVAL;
+		goto out_error;
+	}
+
+	if (close(fd)) {
+		sys_errmsg("close failed on \"%s\"", file);
+		return -1;
+	}
+
+	return rd;
+
+out_error:
+	close(fd);
+	return -1;
+}
+
+/**
+ * read_major - read major and minor numbers from a file.
+ * @file: name of the file to read from
+ * @major: major number is returned here
+ * @minor: minor number is returned here
+ *
+ * This function returns % in case of succes, and %-1 in case of failure.
+ */
+static int read_major(const char *file, int *major, int *minor)
+{
+	int ret;
+	char buf[50];
+
+	ret = read_data(file, buf, 50);
+	if (ret < 0)
+		return ret;
+
+	ret = sscanf(buf, "%d:%d\n", major, minor);
+	if (ret != 2) {
+		errno = EINVAL;
+		return errmsg("\"%s\" does not have major:minor format", file);
+	}
+
+	if (*major < 0 || *minor < 0) {
+		errno = EINVAL;
+		return errmsg("bad major:minor %d:%d in \"%s\"",
+			      *major, *minor, file);
+	}
+
+	return 0;
+}
+
+/**
+ * dev_read_int - read a positive 'int' value from an UBI device sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num:  UBI device number
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_int(const char *patt, int dev_num, int *value)
+{
+	char file[strlen(patt) + 50];
+
+	sprintf(file, patt, dev_num);
+	return read_positive_int(file, value);
+}
+
+/**
+ * vol_read_int - read a positive 'int' value from an UBI volume sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
+{
+	char file[strlen(patt) + 100];
+
+	sprintf(file, patt, dev_num, vol_id);
+	return read_positive_int(file, value);
+}
+
+/**
+ * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_ll(const char *patt, int dev_num, long long *value)
+{
+	char file[strlen(patt) + 50];
+
+	sprintf(file, patt, dev_num);
+	return read_positive_ll(file, value);
+}
+
+/**
+ * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_ll(const char *patt, int dev_num, int vol_id,
+		       long long *value)
+{
+	char file[strlen(patt) + 100];
+
+	sprintf(file, patt, dev_num, vol_id);
+	return read_positive_ll(file, value);
+}
+
+/**
+ * vol_read_data - read data from an UBI volume's sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @buf: buffer to read to
+ * @buf_len: buffer length
+ *
+ * This function returns number of read bytes in case of success and %-1 in
+ * case of failure.
+ */
+static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
+			 int buf_len)
+{
+	char file[strlen(patt) + 100];
+
+	sprintf(file, patt, dev_num, vol_id);
+	return read_data(file, buf, buf_len);
+}
+
+/**
+ * dev_get_major - get major and minor numbers of an UBI device.
+ * @lib: libubi descriptor
+ * @dev_num: UBI device number
+ * @major: major number is returned here
+ * @minor: minor number is returned here
+ *
+ * This function returns zero in case of succes and %-1 in case of failure.
+ */
+static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor)
+{
+	char file[strlen(lib->dev_dev) + 50];
+
+	sprintf(file, lib->dev_dev, dev_num);
+	return read_major(file, major, minor);
+}
+
+/**
+ * vol_get_major - get major and minor numbers of an UBI volume.
+ * @lib: libubi descriptor
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @major: major number is returned here
+ * @minor: minor number is returned here
+ *
+ * This function returns zero in case of succes and %-1 in case of failure.
+ */
+static int vol_get_major(struct libubi *lib, int dev_num, int vol_id,
+			 int *major, int *minor)
+{
+	char file[strlen(lib->vol_dev) + 100];
+
+	sprintf(file, lib->vol_dev, dev_num, vol_id);
+	return read_major(file, major, minor);
+}
+
+/**
+ * vol_node2nums - find UBI device number and volume ID by volume device node
+ *                 file.
+ * @lib: UBI library descriptor
+ * @node: UBI character device node name
+ * @dev_num: UBI device number is returned here
+ * @vol_id: volume ID is returned hers
+ *
+ * This function returns zero in case of succes and %-1 in case of failure.
+ */
+static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,
+			 int *vol_id)
+{
+	struct stat st;
+	struct ubi_info info;
+	int i, fd, major, minor;
+	char file[strlen(lib->ubi_vol) + 100];
+
+	if (stat(node, &st))
+		return sys_errmsg("cannot get information about \"%s\"",
+				  node);
+
+	if (!S_ISCHR(st.st_mode)) {
+		errno = EINVAL;
+		return errmsg("\"%s\" is not a character device", node);
+	}
+
+	major = major(st.st_rdev);
+	minor = minor(st.st_rdev);
+
+	if (minor == 0) {
+		errno = EINVAL;
+		return errmsg("\"%s\" is not a volume character device", node);
+	}
+
+	if (ubi_get_info((libubi_t *)lib, &info))
+		return -1;
+
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		int major1, minor1, ret;
+
+		ret = dev_get_major(lib, i, &major1, &minor1);
+		if (ret) {
+			if (errno == ENOENT)
+				continue;
+			return -1;
+		}
+
+		if (major1 == major)
+			break;
+	}
+
+	if (i > info.highest_dev_num) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	/* Make sure this UBI volume exists */
+	sprintf(file, lib->ubi_vol, i, minor - 1);
+	fd = open(file, O_RDONLY);
+	if (fd == -1) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	*dev_num = i;
+	*vol_id = minor - 1;
+	errno = 0;
+	return 0;
+}
+
+/**
+ * dev_node2num - find UBI device number by its character device node.
+ * @lib: UBI library descriptor
+ * @node: UBI character device node name
+ *
+ * This function returns positive UBI device number in case of success and %-1
+ * in case of failure.
+ */
+static int dev_node2num(struct libubi *lib, const char *node, int *dev_num)
+{
+	struct stat st;
+	struct ubi_info info;
+	int i, major, minor;
+
+	if (stat(node, &st))
+		return sys_errmsg("cannot get information about \"%s\"",
+				  node);
+
+	if (!S_ISCHR(st.st_mode)) {
+		errno = EINVAL;
+		return errmsg("\"%s\" is not a character device", node);
+	}
+
+	major = major(st.st_rdev);
+	minor = minor(st.st_rdev);
+
+	if (minor != 0) {
+		errno = EINVAL;
+		return errmsg("\"%s\" is not an UBI character device", node);
+	}
+
+	if (ubi_get_info((libubi_t *)lib, &info))
+		return -1;
+
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		int major1, minor1, ret;
+
+		ret = dev_get_major(lib, i, &major1, &minor1);
+		if (ret) {
+			if (errno == ENOENT)
+				continue;
+			return -1;
+		}
+
+		if (major1 == major) {
+			if (minor1 != 0) {
+				errmsg("UBI character device minor number is "
+				       "%d, but must be 0", minor1);
+				errno = EINVAL;
+				return -1;
+			}
+			errno = 0;
+			*dev_num = i;
+			return 0;
+		}
+	}
+
+	errno = ENODEV;
+	return -1;
+}
+
+int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num)
+{
+	struct ubi_info info;
+	int i, ret, mtd_num1;
+	struct libubi *lib = desc;
+
+	if (ubi_get_info(desc, &info))
+		return -1;
+
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1);
+		if (ret) {
+			if (errno == ENOENT)
+				continue;
+			return -1;
+		}
+
+		if (mtd_num1 == mtd_num) {
+			errno = 0;
+			*dev_num = i;
+			return 0;
+		}
+	}
+
+	errno = 0;
+	return -1;
+}
+
+libubi_t libubi_open(int required)
 {
 	int fd, version;
 	struct libubi *lib;
@@ -46,132 +519,130 @@ libubi_t libubi_open(void)
 	/* TODO: this must be discovered instead */
 	lib->sysfs = strdup("/sys");
 	if (!lib->sysfs)
-		goto error;
+		goto out_error;
+
+	lib->sysfs_ctrl = mkpath(lib->sysfs, SYSFS_CTRL);
+	if (!lib->sysfs_ctrl)
+		goto out_error;
+
+	lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV);
+	if (!lib->ctrl_dev)
+		goto out_error;
 
 	lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI);
 	if (!lib->sysfs_ubi)
-		goto error;
+		goto out_error;
 
 	/* Make sure UBI is present */
 	fd = open(lib->sysfs_ubi, O_RDONLY);
-	if (fd == -1)
-		goto error;
-	close(fd);
+	if (fd == -1) {
+		if (required)
+			errmsg("cannot open \"%s\", UBI does not seem to "
+			       "exist in system", lib->sysfs_ubi);
+		goto out_error;
+	}
+
+	if (close(fd)) {
+		sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi);
+		goto out_error;
+	}
 
 	lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);
 	if (!lib->ubi_dev)
-		goto error;
+		goto out_error;
 
 	lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);
 	if (!lib->ubi_version)
-		goto error;
+		goto out_error;
 
 	lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);
 	if (!lib->dev_dev)
-		goto error;
+		goto out_error;
 
 	lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);
 	if (!lib->dev_avail_ebs)
-		goto error;
+		goto out_error;
 
 	lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);
 	if (!lib->dev_total_ebs)
-		goto error;
+		goto out_error;
 
 	lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);
 	if (!lib->dev_bad_count)
-		goto error;
+		goto out_error;
 
 	lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);
 	if (!lib->dev_eb_size)
-		goto error;
+		goto out_error;
 
 	lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC);
 	if (!lib->dev_max_ec)
-		goto error;
+		goto out_error;
 
 	lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD);
 	if (!lib->dev_bad_rsvd)
-		goto error;
+		goto out_error;
 
 	lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS);
 	if (!lib->dev_max_vols)
-		goto error;
+		goto out_error;
 
 	lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE);
 	if (!lib->dev_min_io_size)
-		goto error;
+		goto out_error;
+
+	lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM);
+	if (!lib->dev_mtd_num)
+		goto out_error;
 
 	lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT);
 	if (!lib->ubi_vol)
-		goto error;
+		goto out_error;
 
 	lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE);
 	if (!lib->vol_type)
-		goto error;
+		goto out_error;
 
 	lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV);
 	if (!lib->vol_dev)
-		goto error;
+		goto out_error;
 
 	lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT);
 	if (!lib->vol_alignment)
-		goto error;
+		goto out_error;
 
 	lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES);
 	if (!lib->vol_data_bytes)
-		goto error;
+		goto out_error;
 
 	lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS);
 	if (!lib->vol_rsvd_ebs)
-		goto error;
+		goto out_error;
 
 	lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE);
 	if (!lib->vol_eb_size)
-		goto error;
+		goto out_error;
 
 	lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED);
 	if (!lib->vol_corrupted)
-		goto error;
+		goto out_error;
 
 	lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME);
 	if (!lib->vol_name)
-		goto error;
+		goto out_error;
 
-	if (read_int(lib->ubi_version, &version))
-		goto error;
+	if (read_positive_int(lib->ubi_version, &version))
+		goto out_error;
 	if (version != LIBUBI_UBI_VERSION) {
-		fprintf(stderr, "LIBUBI: this library was made for UBI version "
-				"%d, but UBI version %d is detected\n",
-			LIBUBI_UBI_VERSION, version);
-		goto error;
+		errmsg("this library was made for UBI version %d, but UBI "
+		       "version %d is detected\n", LIBUBI_UBI_VERSION, version);
+		goto out_error;
 	}
 
 	return lib;
 
-error:
-	free(lib->vol_corrupted);
-	free(lib->vol_eb_size);
-	free(lib->vol_rsvd_ebs);
-	free(lib->vol_data_bytes);
-	free(lib->vol_alignment);
-	free(lib->vol_dev);
-	free(lib->vol_type);
-	free(lib->ubi_vol);
-	free(lib->dev_min_io_size);
-	free(lib->dev_max_vols);
-	free(lib->dev_bad_rsvd);
-	free(lib->dev_max_ec);
-	free(lib->dev_eb_size);
-	free(lib->dev_bad_count);
-	free(lib->dev_total_ebs);
-	free(lib->dev_avail_ebs);
-	free(lib->dev_dev);
-	free(lib->ubi_version);
-	free(lib->ubi_dev);
-	free(lib->sysfs_ubi);
-	free(lib->sysfs);
-	free(lib);
+out_error:
+	libubi_close((libubi_t)lib);
 	return NULL;
 }
 
@@ -188,6 +659,7 @@ void libubi_close(libubi_t desc)
 	free(lib->vol_dev);
 	free(lib->vol_type);
 	free(lib->ubi_vol);
+	free(lib->dev_mtd_num);
 	free(lib->dev_min_io_size);
 	free(lib->dev_max_vols);
 	free(lib->dev_bad_rsvd);
@@ -200,714 +672,533 @@ void libubi_close(libubi_t desc)
 	free(lib->ubi_version);
 	free(lib->ubi_dev);
 	free(lib->sysfs_ubi);
-	free(lib->sysfs);
-	free(lib);
-}
-
-int ubi_get_info(libubi_t desc, struct ubi_info *info)
-{
-	DIR *sysfs_ubi;
-	struct dirent *dirent;
-	struct libubi *lib = (struct libubi *)desc;
-
-	memset(info, '\0', sizeof(struct ubi_info));
-
-	/*
-	 * We have to scan the UBI sysfs directory to identify how many UBI
-	 * devices are present.
-	 */
-	sysfs_ubi = opendir(lib->sysfs_ubi);
-	if (!sysfs_ubi)
-		return -1;
-
-	info->lowest_dev_num = INT_MAX;
-	while ((dirent = readdir(sysfs_ubi))) {
-		char *name = &dirent->d_name[0];
-		int dev_num, ret;
-
-		ret = sscanf(name, UBI_DEV_NAME_PATT, &dev_num);
-		if (ret == 1) {
-			info->dev_count += 1;
-			if (dev_num > info->highest_dev_num)
-				info->highest_dev_num = dev_num;
-			if (dev_num < info->lowest_dev_num)
-				info->lowest_dev_num = dev_num;
-		}
-	}
-
-	if (info->lowest_dev_num == INT_MAX)
-		info->lowest_dev_num = 0;
-
-	if (read_int(lib->ubi_version, &info->version))
-		goto close;
-
-	return closedir(sysfs_ubi);
-
-close:
-	closedir(sysfs_ubi);
-	return -1;
-}
-
-int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
-{
-	int fd, ret;
-	struct ubi_mkvol_req r;
-	size_t n;
-
-	desc = desc;
-	r.vol_id = req->vol_id;
-	r.alignment = req->alignment;
-	r.bytes = req->bytes;
-	r.vol_type = req->vol_type;
-
-	n = strlen(req->name);
-	if (n > UBI_MAX_VOLUME_NAME)
-		return -1;
-
-	strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
-	r.name_len = n;
-
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return -1;
-
-	ret = ioctl(fd, UBI_IOCMKVOL, &r);
-	if (!ret)
-		req->vol_id = r.vol_id;
-
-	close(fd);
-	return ret;
+	free(lib->ctrl_dev);
+	free(lib->sysfs_ctrl);
+	free(lib->sysfs);
+	free(lib);
 }
 
-int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
+int ubi_attach_mtd(libubi_t desc, const char *node,
+		   struct ubi_attach_request *req)
 {
 	int fd, ret;
+	struct ubi_attach_req r;
 
-	desc = desc;
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return -1;
-
-	ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
-	close(fd);
-	return ret;
-}
-
-int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
-{
-	int fd, ret;
-	struct ubi_rsvol_req req;
+	memset(&r, sizeof(struct ubi_attach_req), '\0');
 
 	desc = desc;
+	r.ubi_num = req->dev_num;
+	r.mtd_num = req->mtd_num;
+	r.vid_hdr_offset = req->vid_hdr_offset;
+
 	fd = open(node, O_RDONLY);
 	if (fd == -1)
-		return -1;
-
-	req.bytes = bytes;
-	req.vol_id = vol_id;
+		return sys_errmsg("cannot open \"%s\"", node);
 
-	ret = ioctl(fd, UBI_IOCRSVOL, &req);
+	ret = ioctl(fd, UBI_IOCATT, &r);
 	close(fd);
-	return ret;
-}
-
-int ubi_update_start(libubi_t desc, int fd, long long bytes)
-{
-	desc = desc;
-	if (ioctl(fd, UBI_IOCVOLUP, &bytes))
+	if (ret == -1)
 		return -1;
-	return 0;
-}
 
-int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
-{
-	int dev_num;
-	struct libubi *lib = (struct libubi *)desc;
+	req->dev_num = r.ubi_num;
 
-	dev_num = find_dev_num(lib, node);
-	if (dev_num == -1)
+#ifdef UDEV_SETTLE_HACK
+	if (system("udevsettle") == -1)
 		return -1;
+#endif
 
-	return ubi_get_dev_info1(desc, dev_num, info);
+	return ret;
 }
 
-int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
+int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
 {
-	DIR *sysfs_ubi;
-	struct dirent *dirent;
-	struct libubi *lib = (struct libubi *)desc;
-
-	memset(info, '\0', sizeof(struct ubi_dev_info));
-	info->dev_num = dev_num;
-
-	sysfs_ubi = opendir(lib->sysfs_ubi);
-	if (!sysfs_ubi)
-		return -1;
-
-	info->lowest_vol_num = INT_MAX;
-	while ((dirent = readdir(sysfs_ubi))) {
-		char *name = &dirent->d_name[0];
-		int vol_id, ret, devno;
+	int ret, ubi_dev;
 
-		ret = sscanf(name, UBI_VOL_NAME_PATT, &devno, &vol_id);
-		if (ret == 2 && devno == dev_num) {
-			info->vol_count += 1;
-			if (vol_id > info->highest_vol_num)
-				info->highest_vol_num = vol_id;
-			if (vol_id < info->lowest_vol_num)
-				info->lowest_vol_num = vol_id;
-		}
+	ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev);
+	if (ret == -1) {
+		errno = ENODEV;
+		return ret;
 	}
 
-	closedir(sysfs_ubi);
-
-	if (info->lowest_vol_num == INT_MAX)
-		info->lowest_vol_num = 0;
-
-	if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_ebs))
-		return -1;
-	if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_ebs))
-		return -1;
-	if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
-		return -1;
-	if (dev_read_int(lib->dev_eb_size, dev_num, &info->eb_size))
-		return -1;
-	if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
-		return -1;
-	if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
-		return -1;
-	if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
-		return -1;
-	if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
-		return -1;
-
-	info->avail_bytes = info->avail_ebs * info->eb_size;
-	info->total_bytes = info->total_ebs * info->eb_size;
-
-	return 0;
+	return ubi_remove_dev(desc, node, ubi_dev);
 }
 
-int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
+int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
 {
-	int vol_id, dev_num;
-	struct libubi *lib = (struct libubi *)desc;
+	int fd, ret;
 
-	dev_num = find_dev_num_vol(lib, node);
-	if (dev_num == -1)
-		return -1;
+	desc = desc;
+
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return sys_errmsg("cannot open \"%s\"", node);
+	ret = ioctl(fd, UBI_IOCDET, &ubi_dev);
+	if (ret == -1)
+		goto out_close;
 
-	vol_id = find_vol_num(lib, dev_num, node);
-	if (vol_id == -1)
+#ifdef UDEV_SETTLE_HACK
+	if (system("udevsettle") == -1)
 		return -1;
+#endif
 
-	return ubi_get_vol_info1(desc, dev_num, vol_id, info);
+out_close:
+	close(fd);
+	return ret;
 }
 
-int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
-		      struct ubi_vol_info *info)
+int ubi_node_type(libubi_t desc, const char *node)
 {
-	int ret;
+	struct stat st;
+	struct ubi_info info;
+	int i, fd, major, minor;
 	struct libubi *lib = (struct libubi *)desc;
-	char buf[50];
-
-	memset(info, '\0', sizeof(struct ubi_vol_info));
-	info->dev_num = dev_num;
-	info->vol_id = vol_id;
+	char file[strlen(lib->ubi_vol) + 100];
 
-	ret = vol_read_data(lib->vol_type, dev_num, vol_id, &buf[0], 50);
-	if (ret < 0)
-		return -1;
+	if (stat(node, &st))
+		return sys_errmsg("cannot get information about \"%s\"",
+				  node);
 
-	if (strncmp(&buf[0], "static\n", ret) == 0)
-		info->type = UBI_STATIC_VOLUME;
-	else if (strncmp(&buf[0], "dynamic\n", ret) == 0)
-		info->type = UBI_DYNAMIC_VOLUME;
-	else {
-		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
+	if (!S_ISCHR(st.st_mode)) {
+		errmsg("\"%s\" is not a character device", node);
 		errno = EINVAL;
 		return -1;
 	}
 
-	ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
-			   &info->alignment);
-	if (ret)
-		return -1;
-	ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
-			  &info->data_bytes);
-	if (ret)
-		return -1;
-	ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_ebs);
-	if (ret)
-		return -1;
-	ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->eb_size);
-	if (ret)
-		return -1;
-	ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
-			   &info->corrupted);
-	if (ret)
-		return -1;
-	info->rsvd_bytes = info->eb_size * info->rsvd_ebs;
+	major = major(st.st_rdev);
+	minor = minor(st.st_rdev);
 
-	ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
-			    UBI_VOL_NAME_MAX + 2);
-	if (ret < 0)
+	if (ubi_get_info((libubi_t *)lib, &info))
 		return -1;
 
-	info->name[ret - 1] = '\0';
-	return 0;
-}
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		int major1, minor1, ret;
 
-/**
- * read_int - read an 'int' value from a file.
- *
- * @file   the file to read from
- * @value  the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int read_int(const char *file, int *value)
-{
-	int fd, rd;
-	char buf[50];
+		ret = dev_get_major(lib, i, &major1, &minor1);
+		if (ret) {
+			if (errno == ENOENT)
+				continue;
+			if (!errno)
+				goto out_not_ubi;
+			return -1;
+		}
 
-	fd = open(file, O_RDONLY);
-	if (fd == -1)
-		return -1;
+		if (major1 == major)
+			break;
+	}
 
-	rd = read(fd, &buf[0], 50);
-	if (rd == -1)
-		goto error;
+	if (i > info.highest_dev_num)
+		goto out_not_ubi;
 
-	if (sscanf(&buf[0], "%d\n", value) != 1) {
-		/* This must be a UBI bug */
-		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-		errno = EINVAL;
-		goto error;
+	if (minor == 0)
+		return 1;
+
+	/* This is supposdely an UBI volume device node */
+	sprintf(file, lib->ubi_vol, i, minor - 1);
+	fd = open(file, O_RDONLY);
+	if (fd == -1) {
+		sys_errmsg("cannot open \"%s\"", node);
+		return -1;
 	}
 
-	close(fd);
-	return 0;
+	return 2;
 
-error:
-	close(fd);
+out_not_ubi:
+	errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to "
+	       "any UBI device or volume", node, major, minor);
+	errno = 0;
 	return -1;
 }
 
-/**
- * dev_read_int - read an 'int' value from an UBI device's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @value    the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_int(const char *patt, int dev_num, int *value)
+int ubi_get_info(libubi_t desc, struct ubi_info *info)
 {
-	int fd, rd;
-	char buf[50];
-	char file[strlen(patt) + 50];
-
-	sprintf(&file[0], patt, dev_num);
-	fd = open(&file[0], O_RDONLY);
-	if (fd == -1)
-		return -1;
+	DIR *sysfs_ubi;
+	struct dirent *dirent;
+	struct libubi *lib = (struct libubi *)desc;
 
-	rd = read(fd, &buf[0], 50);
-	if (rd == -1)
-		goto error;
+	memset(info, '\0', sizeof(struct ubi_info));
 
-	if (sscanf(&buf[0], "%d\n", value) != 1) {
-		/* This must be a UBI bug */
-		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-		errno = EINVAL;
-		goto error;
+	if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) {
+		/*
+		 * Older UBI versions did not have control device, so we do not
+		 * panic here for compatibility reasons. May be few years later
+		 * we could return -1 here, but for now just set major:minor to
+		 * -1.
+		 */
+		info->ctrl_major = info->ctrl_minor = -1;
 	}
 
-	close(fd);
-	return 0;
+	/*
+	 * We have to scan the UBI sysfs directory to identify how many UBI
+	 * devices are present.
+	 */
+	sysfs_ubi = opendir(lib->sysfs_ubi);
+	if (!sysfs_ubi)
+		return -1;
 
-error:
-	close(fd);
-	return -1;
-}
+	info->lowest_dev_num = INT_MAX;
+	while (1) {
+		int dev_num, ret;
+		char tmp_buf[256];
 
-/**
- * dev_read_ll - read a 'long long' value from an UBI device's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @value    the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_ll(const char *patt, int dev_num, long long *value)
-{
-	int fd, rd;
-	char buf[50];
-	char file[strlen(patt) + 50];
+		errno = 0;
+		dirent = readdir(sysfs_ubi);
+		if (!dirent)
+			break;
 
-	sprintf(&file[0], patt, dev_num);
-	fd = open(&file[0], O_RDONLY);
-	if (fd == -1)
-		return -1;
+		if (strlen(dirent->d_name) > 256) {
+			errmsg("invalid entry in %s: \"%s\"",
+			       lib->sysfs_ubi, dirent->d_name);
+			goto out_close;
+		}
 
-	rd = read(fd, &buf[0], 50);
-	if (rd == -1)
-		goto error;
+		ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s",
+			     &dev_num, tmp_buf);
+		if (ret == 1) {
+			info->dev_count += 1;
+			if (dev_num > info->highest_dev_num)
+				info->highest_dev_num = dev_num;
+			if (dev_num < info->lowest_dev_num)
+				info->lowest_dev_num = dev_num;
+		}
+	}
 
-	if (sscanf(&buf[0], "%lld\n", value) != 1) {
-		/* This must be a UBI bug */
-		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-		errno = EINVAL;
-		goto error;
+	if (!dirent && errno) {
+		sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
+		goto out_close;
 	}
 
-	close(fd);
+	if (closedir(sysfs_ubi))
+		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
+
+	if (info->lowest_dev_num == INT_MAX)
+		info->lowest_dev_num = 0;
+
+	if (read_positive_int(lib->ubi_version, &info->version))
+		return -1;
+
 	return 0;
 
-error:
-	close(fd);
+out_close:
+	closedir(sysfs_ubi);
 	return -1;
 }
 
-/**
- * dev_read_data - read data from an UBI device's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @buf      buffer to read data to
- * @buf_len  buffer length
- *
- * This function returns number of read bytes in case of success and %-1 in
- * case of failure.
- */
-static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len)
+int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
 {
-	int fd, rd;
-	char file[strlen(patt) + 50];
+	int fd, ret;
+	struct ubi_mkvol_req r;
+	size_t n;
 
-	sprintf(&file[0], patt, dev_num);
-	fd = open(&file[0], O_RDONLY);
-	if (fd == -1)
-		return -1;
+	memset(&r, sizeof(struct ubi_mkvol_req), '\0');
 
-	rd = read(fd, buf, buf_len);
-	if (rd == -1) {
-		close(fd);
-		return -1;
-	}
+	desc = desc;
+	r.vol_id = req->vol_id;
+	r.alignment = req->alignment;
+	r.bytes = req->bytes;
+	r.vol_type = req->vol_type;
 
-	close(fd);
-	return rd;
-}
+	n = strlen(req->name);
+	if (n > UBI_MAX_VOLUME_NAME)
+		return -1;
 
-/**
- * vol_read_int - read an 'int' value from an UBI volume's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @vol_id   volume identifier
- * @value    the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
-{
-	int fd, rd;
-	char buf[50];
-	char file[strlen(patt) + 100];
+	strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
+	r.name_len = n;
 
-	sprintf(&file[0], patt, dev_num, vol_id);
-	fd = open(&file[0], O_RDONLY);
+	fd = open(node, O_RDONLY);
 	if (fd == -1)
-		return -1;
+		return sys_errmsg("cannot open \"%s\"", node);
 
-	rd = read(fd, &buf[0], 50);
-	if (rd == -1)
-		goto error;
+	ret = ioctl(fd, UBI_IOCMKVOL, &r);
+	if (ret == -1)
+		goto out_close;
 
-	if (sscanf(&buf[0], "%d\n", value) != 1) {
-		/* This must be a UBI bug */
-		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-		errno = EINVAL;
-		goto error;
-	}
+	req->vol_id = r.vol_id;
 
-	close(fd);
-	return 0;
+#ifdef UDEV_SETTLE_HACK
+	if (system("udevsettle") == -1)
+		return -1;
+#endif
 
-error:
+out_close:
 	close(fd);
-	return -1;
+	return ret;
 }
 
-/**
- * vol_read_ll - read a 'long long' value from an UBI volume's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @vol_id   volume identifier
- * @value    the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_ll(const char *patt, int dev_num, int vol_id,
-		       long long *value)
+int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
 {
-	int fd, rd;
-	char buf[50];
-	char file[strlen(patt) + 100];
+	int fd, ret;
 
-	sprintf(&file[0], patt, dev_num, vol_id);
-	fd = open(&file[0], O_RDONLY);
+	desc = desc;
+	fd = open(node, O_RDONLY);
 	if (fd == -1)
-		return -1;
+		return sys_errmsg("cannot open \"%s\"", node);
 
-	rd = read(fd, &buf[0], 50);
-	if (rd == -1)
-		goto error;
-
-	if (sscanf(&buf[0], "%lld\n", value) != 1) {
-		/* This must be a UBI bug */
-		fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-		errno = EINVAL;
-		goto error;
-	}
+	ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
+	if (ret == -1)
+		goto out_close;
 
-	close(fd);
-	return 0;
+#ifdef UDEV_SETTLE_HACK
+	if (system("udevsettle") == -1)
+		return -1;
+#endif
 
-error:
+out_close:
 	close(fd);
-	return -1;
+	return ret;
 }
 
-/**
- * vol_read_data - read data from an UBI volume's sysfs file.
- *
- * @patt     the file pattern to read from
- * @dev_num  UBI device number
- * @vol_id   volume identifier
- * @buf      buffer to read to
- * @buf_len  buffer length
- *
- * This function returns number of read bytes in case of success and %-1 in
- * case of failure.
- */
-static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
-			 int buf_len)
+int ubi_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol)
 {
-	int fd, rd;
-	char file[strlen(patt) + 100];
+	int fd, ret;
 
-	sprintf(&file[0], patt, dev_num, vol_id);
-	fd = open(&file[0], O_RDONLY);
+	fd = open(node, O_RDONLY);
 	if (fd == -1)
 		return -1;
+	ret = ioctl(fd, UBI_IOCRNVOL, rnvol);
+	if (ret == -1)
+		goto out_close;
 
-	rd = read(fd, buf, buf_len);
-	if (rd == -1) {
-		close(fd);
+#ifdef UDEV_SETTLE_HACK
+	if (system("udevsettle") == -1)
 		return -1;
-	}
+#endif
 
+out_close:
 	close(fd);
-	return rd;
+	return ret;
 }
 
-/**
- * mkpath - compose full path from 2 given components.
- *
- * @path  first component
- * @name  second component
- *
- * This function returns the resulting path in case of success and %NULL in
- * case of failure.
- */
-static char *mkpath(const char *path, const char *name)
+int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
 {
-	char *n;
-	int len1 = strlen(path);
-	int len2 = strlen(name);
+	int fd, ret;
+	struct ubi_rsvol_req req;
 
-	n = malloc(len1 + len2 + 2);
-	if (!n)
-		return NULL;
+	desc = desc;
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return sys_errmsg("cannot open \"%s\"", node);
 
-	memcpy(n, path, len1);
-	if (n[len1 - 1] != '/')
-		n[len1++] = '/';
+	req.bytes = bytes;
+	req.vol_id = vol_id;
 
-	memcpy(n + len1, name, len2 + 1);
-	return n;
+	ret = ioctl(fd, UBI_IOCRSVOL, &req);
+	close(fd);
+	return ret;
 }
 
-/**
- * find_dev_num - find UBI device number by its character device node.
- *
- * @lib   UBI library descriptor
- * @node  UBI character device node name
- *
- * This function returns positive UBI device number in case of success and %-1
- * in case of failure.
- */
-static int find_dev_num(struct libubi *lib, const char *node)
+int ubi_update_start(libubi_t desc, int fd, long long bytes)
 {
-	struct stat st;
-	struct ubi_info info;
-	int i, major, minor;
-
-	if (stat(node, &st))
+	desc = desc;
+	if (ioctl(fd, UBI_IOCVOLUP, &bytes))
 		return -1;
+	return 0;
+}
 
-	if (!S_ISCHR(st.st_mode)) {
-		errno = EINVAL;
-		return -1;
-	}
+int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype)
+{
+	struct ubi_leb_change_req req;
 
-	major = major(st.st_rdev);
-	minor = minor(st.st_rdev);
+	desc = desc;
+	memset(&req, 0, sizeof(struct ubi_leb_change_req));
+	req.lnum = lnum;
+	req.bytes = bytes;
+	req.dtype = dtype;
 
-	if (minor != 0) {
-		errno = -EINVAL;
+	if (ioctl(fd, UBI_IOCEBCH, &req))
 		return -1;
-	}
+	return 0;
+}
 
-	if (ubi_get_info((libubi_t *)lib, &info))
+int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
+{
+	DIR *sysfs_ubi;
+	struct dirent *dirent;
+	struct libubi *lib = (struct libubi *)desc;
+
+	memset(info, '\0', sizeof(struct ubi_dev_info));
+	info->dev_num = dev_num;
+
+	sysfs_ubi = opendir(lib->sysfs_ubi);
+	if (!sysfs_ubi)
 		return -1;
 
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		int major1, minor1, ret;
-		char buf[50];
+	info->lowest_vol_id = INT_MAX;
 
-		ret = dev_read_data(lib->dev_dev, i, &buf[0], 50);
-		if (ret < 0)
-			return -1;
+	while (1) {
+		int vol_id, ret, devno;
+		char tmp_buf[256];
 
-		ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
-		if (ret != 2) {
-			fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-			errno = EINVAL;
-			return -1;
+		errno = 0;
+		dirent = readdir(sysfs_ubi);
+		if (!dirent)
+			break;
+
+		if (strlen(dirent->d_name) > 256) {
+			errmsg("invalid entry in %s: \"%s\"",
+			       lib->sysfs_ubi, dirent->d_name);
+			goto out_close;
 		}
 
-		if (minor1 == minor && major1 == major)
-			return i;
+		ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf);
+		if (ret == 2 && devno == dev_num) {
+			info->vol_count += 1;
+			if (vol_id > info->highest_vol_id)
+				info->highest_vol_id = vol_id;
+			if (vol_id < info->lowest_vol_id)
+				info->lowest_vol_id = vol_id;
+		}
 	}
 
-	errno = ENOENT;
-	return -1;
-}
+	if (!dirent && errno) {
+		sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
+		goto out_close;
+	}
 
-/**
- * find_dev_num_vol - find UBI device number by volume character device node.
- *
- * @lib   UBI library descriptor
- * @node  UBI character device node name
- *
- * This function returns positive UBI device number in case of success and %-1
- * in case of failure.
- */
-static int find_dev_num_vol(struct libubi *lib, const char *node)
-{
-	struct stat st;
-	struct ubi_info info;
-	int i, major;
+	if (closedir(sysfs_ubi))
+		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
 
-	if (stat(node, &st))
-		return -1;
+	if (info->lowest_vol_id == INT_MAX)
+		info->lowest_vol_id = 0;
 
-	if (!S_ISCHR(st.st_mode)) {
-		errno = EINVAL;
+	if (dev_get_major(lib, dev_num, &info->major, &info->minor))
 		return -1;
-	}
-
-	major = major(st.st_rdev);
 
-	if (minor(st.st_rdev) == 0) {
-		errno = -EINVAL;
+	if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs))
 		return -1;
-	}
-
-	if (ubi_get_info((libubi_t *)lib, &info))
+	if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs))
+		return -1;
+	if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
+		return -1;
+	if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size))
+		return -1;
+	if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
+		return -1;
+	if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
+		return -1;
+	if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
+		return -1;
+	if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
 		return -1;
 
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		int major1, minor1, ret;
-		char buf[50];
+	info->avail_bytes = info->avail_lebs * info->leb_size;
+	info->total_bytes = info->total_lebs * info->leb_size;
 
-		ret = dev_read_data(lib->dev_dev, i, &buf[0], 50);
-		if (ret < 0)
-			return -1;
+	return 0;
 
-		ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
-		if (ret != 2) {
-			fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-			errno = EINVAL;
-			return -1;
-		}
+out_close:
+	closedir(sysfs_ubi);
+	return -1;
+}
 
-		if (major1 == major)
-			return i;
-	}
+int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
+{
+	int dev_num;
+	struct libubi *lib = (struct libubi *)desc;
 
-	errno = ENOENT;
-	return -1;
+	if (dev_node2num(lib, node, &dev_num))
+		return -1;
+
+	return ubi_get_dev_info1(desc, dev_num, info);
 }
 
-/**
- * find_vol_num - find UBI volume number by its character device node.
- *
- * @lib      UBI library descriptor
- * @dev_num  UBI device number
- * @node     UBI volume character device node name
- *
- * This function returns positive UBI volume number in case of success and %-1
- * in case of failure.
- */
-static int find_vol_num(struct libubi *lib, int dev_num, const char *node)
+int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
+		      struct ubi_vol_info *info)
 {
-	struct stat st;
-	struct ubi_dev_info info;
-	int i, major, minor;
+	int ret;
+	struct libubi *lib = (struct libubi *)desc;
+	char buf[50];
 
-	if (stat(node, &st))
+	memset(info, '\0', sizeof(struct ubi_vol_info));
+	info->dev_num = dev_num;
+	info->vol_id = vol_id;
+
+	if (dev_get_major(lib, dev_num, &info->dev_major, &info->dev_minor))
+		return -1;
+	if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor))
 		return -1;
 
-	if (!S_ISCHR(st.st_mode)) {
+	ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50);
+	if (ret < 0)
+		return -1;
+
+	if (strncmp(buf, "static\n", ret) == 0)
+		info->type = UBI_STATIC_VOLUME;
+	else if (strncmp(buf, "dynamic\n", ret) == 0)
+		info->type = UBI_DYNAMIC_VOLUME;
+	else {
+		errmsg("bad value at \"%s\"", buf);
 		errno = EINVAL;
 		return -1;
 	}
 
-	major = major(st.st_rdev);
-	minor = minor(st.st_rdev);
+	ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
+			   &info->alignment);
+	if (ret)
+		return -1;
+	ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
+			  &info->data_bytes);
+	if (ret)
+		return -1;
+	ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs);
+	if (ret)
+		return -1;
+	ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size);
+	if (ret)
+		return -1;
+	ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
+			   &info->corrupted);
+	if (ret)
+		return -1;
+	info->rsvd_bytes = info->leb_size * info->rsvd_lebs;
 
-	if (minor == 0) {
-		errno = -EINVAL;
+	ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
+			    UBI_VOL_NAME_MAX + 2);
+	if (ret < 0)
 		return -1;
-	}
 
-	if (ubi_get_dev_info1((libubi_t *)lib, dev_num, &info))
+	info->name[ret - 1] = '\0';
+	return 0;
+}
+
+int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
+{
+	int vol_id, dev_num;
+	struct libubi *lib = (struct libubi *)desc;
+
+	if (vol_node2nums(lib, node, &dev_num, &vol_id))
 		return -1;
 
-	for (i = info.lowest_vol_num; i <= info.highest_vol_num; i++) {
-		int major1, minor1, ret;
-		char buf[50];
+	return ubi_get_vol_info1(desc, dev_num, vol_id, info);
+}
 
-		ret = vol_read_data(lib->vol_dev,  dev_num, i, &buf[0], 50);
-		if (ret < 0)
-			return -1;
+int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name,
+			 struct ubi_vol_info *info)
+{
+	int i, err;
+	unsigned int nlen = strlen(name);
+	struct ubi_dev_info dev_info;
+
+	if (nlen == 0) {
+		errmsg("bad \"name\" input parameter");
+		errno = EINVAL;
+		return -1;
+	}
+
+	err = ubi_get_dev_info1(desc, dev_num, &dev_info);
+	if (err)
+		return err;
 
-		ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1);
-		if (ret != 2) {
-			fprintf(stderr, "LIBUBI: bad value at sysfs file\n");
-			errno = EINVAL;
+	for (i = dev_info.lowest_vol_id;
+	     i <= dev_info.highest_vol_id; i++) {
+		err = ubi_get_vol_info1(desc, dev_num, i, info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
 			return -1;
 		}
 
-		if (minor1 == minor && major1 == major)
-			return i;
+		if (nlen == strlen(info->name) && !strcmp(name, info->name))
+			return 0;
 	}
 
 	errno = ENOENT;
diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h
index e68b791..2e664b8 100644
--- a/ubi-utils/src/libubi_int.h
+++ b/ubi-utils/src/libubi_int.h
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Author: Artem B. Bityutskiy
+ * Author: Artem Bityutskiy
  *
  * UBI (Unsorted Block Images) library.
  */
@@ -23,20 +23,31 @@
 #ifndef __LIBUBI_INT_H__
 #define __LIBUBI_INT_H__
 
+#include <string.h>
+#include <errno.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
- * UBI heavily makes use of the sysfs file system to interact with users-pace.
  * The below are pre-define UBI file and directory names.
+ *
+ * Note, older kernels put 'ubiX_Y' directories straight to '/sys/class/ubi/'.
+ * New kernels puts 'ubiX_Y' directories to '/sys/class/ubi/ubiX/', which is
+ * saner. And for compatibility reasons it also puts symlinks to 'ubiX_Y'
+ * directories to '/sys/class/ubi/'. For now libubi assumes old layout.
  */
 
 #define SYSFS_UBI         "class/ubi"
-#define UBI_DEV_NAME_PATT "ubi%d"
+#define SYSFS_CTRL        "class/misc/ubi_ctrl/"
+
+#define CTRL_DEV          "dev"
+
 #define UBI_VER           "version"
+#define UBI_DEV_NAME_PATT "ubi%d"
+
 #define DEV_DEV           "dev"
-#define UBI_VOL_NAME_PATT "ubi%d_%d"
 #define DEV_AVAIL_EBS     "avail_eraseblocks"
 #define DEV_TOTAL_EBS     "total_eraseblocks"
 #define DEV_BAD_COUNT     "bad_peb_count"
@@ -45,6 +56,9 @@ extern "C" {
 #define DEV_MAX_RSVD      "reserved_for_bad"
 #define DEV_MAX_VOLS      "max_vol_count"
 #define DEV_MIN_IO_SIZE   "min_io_size"
+#define DEV_MTD_NUM       "mtd_num"
+
+#define UBI_VOL_NAME_PATT "ubi%d_%d"
 #define VOL_TYPE          "type"
 #define VOL_DEV           "dev"
 #define VOL_ALIGNMENT     "alignment"
@@ -56,34 +70,37 @@ extern "C" {
 
 /**
  * libubi - UBI library description data structure.
- *
- * @sysfs            sysfs file system path
- * @sysfs_ubi        UBI directory in sysfs
- * @ubi_dev          UBI device sysfs directory pattern
- * @ubi_version      UBI version file sysfs path
- * @dev_dev          UBI device's major/minor numbers file pattern
- * @dev_avail_ebs    count of available eraseblocks sysfs path pattern
- * @dev_total_ebs    total eraseblocks count sysfs path pattern
- * @dev_bad_count    count of bad eraseblocks sysfs path pattern
- * @dev_eb_size      size of UBI device's eraseblocks sysfs path pattern
- * @dev_max_ec       maximum erase counter sysfs path pattern
- * @dev_bad_rsvd     count of physical eraseblock reserved for bad eraseblocks
- *                   handling
- * @dev_max_vols     maximum volumes number count sysfs path pattern
- * @dev_min_io_size  minimum I/O unit size sysfs path pattern
- * @ubi_vol          UBI volume sysfs directory pattern
- * @vol_type         volume type sysfs path pattern
- * @vol_dev          volume's major/minor numbers file pattern
- * @vol_alignment    volume alignment sysfs path pattern
- * @vol_data_bytes   volume data size sysfs path pattern
- * @vol_rsvd_ebs     volume reserved size sysfs path pattern
- * @vol_eb_size      volume eraseblock size sysfs path pattern
- * @vol_corrupted    volume corruption flag sysfs path pattern
- * @vol_name         volume name sysfs path pattern
+ * @sysfs: sysfs file system path
+ * @sysfs_ctrl: UBI control device directory in sysfs
+ * @ctrl_dev: UBI control device major/minor numbers sysfs file
+ * @sysfs_ubi: UBI directory in sysfs
+ * @ubi_dev: UBI device sysfs directory pattern
+ * @ubi_version: UBI version file sysfs path
+ * @dev_dev: UBI device major/minor numbers file pattern
+ * @dev_avail_ebs: count of available eraseblocks sysfs path pattern
+ * @dev_total_ebs: total eraseblocks count sysfs path pattern
+ * @dev_bad_count: count of bad eraseblocks sysfs path pattern
+ * @dev_eb_size: size of UBI device's eraseblocks sysfs path pattern
+ * @dev_max_ec: maximum erase counter sysfs path pattern
+ * @dev_bad_rsvd: count of physical eraseblock reserved for bad eraseblocks
+ *                handling
+ * @dev_max_vols: maximum volumes number count sysfs path pattern
+ * @dev_min_io_size: minimum I/O unit size sysfs path pattern
+ * @ubi_vol: UBI volume sysfs directory pattern
+ * @vol_type: volume type sysfs path pattern
+ * @vol_dev: volume major/minor numbers file pattern
+ * @vol_alignment: volume alignment sysfs path pattern
+ * @vol_data_bytes: volume data size sysfs path pattern
+ * @vol_rsvd_ebs: volume reserved size sysfs path pattern
+ * @vol_eb_size: volume eraseblock size sysfs path pattern
+ * @vol_corrupted: volume corruption flag sysfs path pattern
+ * @vol_name: volume name sysfs path pattern
  */
 struct libubi
 {
 	char *sysfs;
+	char *sysfs_ctrl;
+	char *ctrl_dev;
 	char *sysfs_ubi;
 	char *ubi_dev;
 	char *ubi_version;
@@ -96,6 +113,7 @@ struct libubi
 	char *dev_bad_rsvd;
 	char *dev_max_vols;
 	char *dev_min_io_size;
+	char *dev_mtd_num;
 	char *ubi_vol;
 	char *vol_type;
 	char *vol_dev;
@@ -108,20 +126,6 @@ struct libubi
 	char *vol_max_count;
 };
 
-static int read_int(const char *file, int *value);
-static int dev_read_int(const char *patt, int dev_num, int *value);
-static int dev_read_ll(const char *patt, int dev_num, long long *value);
-static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len);
-static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value);
-static int vol_read_ll(const char *patt, int dev_num, int vol_id,
-		       long long *value);
-static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
-			 int buf_len);
-static char *mkpath(const char *path, const char *name);
-static int find_dev_num(struct libubi *lib, const char *node);
-static int find_dev_num_vol(struct libubi *lib, const char *node);
-static int find_vol_num(struct libubi *lib, int dev_num, const char *node);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/ubi-utils/src/libubigen.c b/ubi-utils/src/libubigen.c
index 1793009..91bb274 100644
--- a/ubi-utils/src/libubigen.c
+++ b/ubi-utils/src/libubigen.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (C) 2008 Nokia Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,474 +15,316 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Generating UBI images.
  *
- * Author: Oliver Lohmann
- *
- * Add UBI headers to binary data.
+ * Authors: Oliver Lohmann
+ *          Artem Bityutskiy
  */
 
 #include <stdlib.h>
 #include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
+#include <unistd.h>
 #include <string.h>
+
 #include <mtd/ubi-media.h>
 #include <mtd_swab.h>
-
-#include "config.h"
-#include "ubigen.h"
+#include <libubigen.h>
 #include "crc32.h"
-
-#define UBI_NAME_SIZE		256
-#define DEFAULT_VID_OFFSET	((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE))
-#define MIN(a,b)		((a) < (b) ? (a) : (b))
-
-static uint32_t crc32_table[256];
-
-struct ubi_info {
-	struct ubi_vid_hdr* v;	/* Volume ID header */
-	struct ubi_ec_hdr* ec;	/* Erase count header */
-
-	FILE* fp_in;		/* Input Stream */
-	FILE* fp_out;		/* Output stream */
-
-	size_t eb_size;		/* Physical EB size in bytes */
-	size_t leb_size;	/* Size of a logical EB in a physical EB */
-	size_t leb_total;	/* Total input size in logical EB */
-	size_t alignment;	/* Block alignment */
-	size_t data_pad;	/* Size of padding in each physical EB */
-
-	size_t bytes_total;	/* Total input size in bytes */
-	size_t bytes_read;	/* Nymber of read bytes (total) */
-
-	uint32_t blks_written;	/* Number of written logical EB */
-
-	uint8_t* buf;		/* Allocated buffer */
-	uint8_t* ptr_ec_hdr;	/* Pointer to EC hdr in buf */
-	uint8_t* ptr_vid_hdr;	/* Pointer to VID hdr in buf */
-	uint8_t* ptr_data;	/* Pointer to data region in buf */
-};
-
-
-static uint32_t
-byte_to_blk(uint64_t byte, uint32_t eb_size)
-{
-	return (byte % eb_size) == 0
-		? (byte / eb_size)
-		: (byte / eb_size) + 1;
-}
-
-static int
-validate_ubi_info(ubi_info_t u)
-{
-	if ((u->v->vol_type != UBI_VID_DYNAMIC) &&
-	    (u->v->vol_type != UBI_VID_STATIC)) {
-		return EUBIGEN_INVALID_TYPE;
-	}
-
-	if (be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) {
-		return EUBIGEN_INVALID_HDR_OFFSET;
-	}
-
-	return 0;
-}
-
-static int
-skip_blks(ubi_info_t u, uint32_t blks)
-{
-	uint32_t i;
-	size_t read = 0, to_read = 0;
-
-	/* Step to a maximum of leb_total - 1 to keep the
-	   restrictions. */
-	for (i = 0; i < MIN(blks, u->leb_total-1); i++) {
-		/* Read in data */
-		to_read = MIN(u->leb_size,
-			      (u->bytes_total - u->bytes_read));
-		read = fread(u->ptr_data, 1, to_read, u->fp_in);
-		if (read != to_read) {
-			return -EIO;
-		}
-		u->bytes_read += read;
-		u->blks_written++;
-	}
-
-	return 0;
-}
-
-static void
-clear_buf(ubi_info_t u)
-{
-	memset(u->buf, 0xff, u->eb_size);
-}
-
-static void
-write_ec_hdr(ubi_info_t u)
-{
-	memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE);
-}
-
-static int
-fill_data_buffer_from_file(ubi_info_t u, size_t* read)
-{
-	size_t to_read = 0;
-
-	if (u-> fp_in == NULL)
-		return -EIO;
-
-	to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read));
-	*read = fread(u->ptr_data, 1, to_read, u->fp_in);
-	if (*read != to_read) {
-		return -EIO;
-	}
-	return 0;
-}
-
-static void
-add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action)
-{
-	uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
-				 u->ptr_data, data_size);
-
-	u->v->data_size = cpu_to_be32(data_size);
-	u->v->data_crc = cpu_to_be32(crc);
-
-	if (action & BROKEN_DATA_CRC) {
-		u->v->data_crc =
-			cpu_to_be32(be32_to_cpu(u->v->data_crc) + 1);
-	}
-	if (action & BROKEN_DATA_SIZE) {
-		u->v->data_size =
-			cpu_to_be32(be32_to_cpu(u->v->data_size) + 1);
-	}
-}
-
-static void
-write_vid_hdr(ubi_info_t u, ubigen_action_t action)
+#include "common.h"
+
+#define PROGRAM_NAME "libubigen"
+
+/**
+ * ubigen_info_init - initialize libubigen.
+ * @ui: libubigen information
+ * @peb_size: flash physical eraseblock size
+ * @min_io_size: flash minimum input/output unit size
+ * @subpage_size: flash sub-page, if present (has to be equivalent to
+ *                @min_io_size if does not exist)
+ * @vid_hdr_offs: offset of the VID header
+ * @ubi_ver: UBI version
+ */
+void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
+		      int subpage_size, int vid_hdr_offs, int ubi_ver)
 {
-	uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
-				 u->v, UBI_VID_HDR_SIZE_CRC);
-	/* Write VID header */
-	u->v->hdr_crc = cpu_to_be32(crc);
-	if (action & BROKEN_HDR_CRC) {
-		u->v->hdr_crc = cpu_to_be32(be32_to_cpu(u->v->hdr_crc) + 1);
+	if (!vid_hdr_offs) {
+		vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1;
+		vid_hdr_offs /= subpage_size;
+		vid_hdr_offs *= subpage_size;
 	}
-	memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE);
-}
 
-static int
-write_to_output_stream(ubi_info_t u)
-{
-	size_t written;
-
-	written = fwrite(u->buf, 1, u->eb_size, u->fp_out);
-	if (written != u->eb_size) {
-		return -EIO;
-	}
-	return 0;
+	ui->peb_size = peb_size;
+	ui->min_io_size = min_io_size;
+	ui->vid_hdr_offs = vid_hdr_offs;
+	ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1;
+	ui->data_offs /= min_io_size;
+	ui->data_offs *= min_io_size;
+	ui->leb_size = peb_size - ui->data_offs;
+	ui->ubi_ver = ubi_ver;
+
+	ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE;
+	if (ui->max_volumes > UBI_MAX_VOLUMES)
+		ui->max_volumes = UBI_MAX_VOLUMES;
+	ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE;
 }
 
-int
-ubigen_write_leb(ubi_info_t u, ubigen_action_t action)
+/**
+ * ubigen_create_empty_vtbl - creates empty volume table.
+ *
+ * This function creates an empty volume table and returns a pointer to it in
+ * case of success and %NULL in case of failure. The returned object has to be
+ * freed with 'free()' call.
+ */
+struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui)
 {
-	int rc = 0;
-	size_t read = 0;
-
-	clear_buf(u);
-	write_ec_hdr(u);
+	struct ubi_vtbl_record *vtbl;
+	int i;
 
-	rc = fill_data_buffer_from_file(u, &read);
-	if (rc != 0)
-		return rc;
-
-	if (u->v->vol_type == UBI_VID_STATIC)  {
-		add_static_info(u, read, action);
+	vtbl = calloc(1, ui->vtbl_size);
+	if (!vtbl) {
+		sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
+		return NULL;
 	}
 
-	u->v->lnum = cpu_to_be32(u->blks_written);
-
-	if (action & MARK_AS_UPDATE) {
-		u->v->copy_flag = (u->v->copy_flag)++;
+	for (i = 0; i < ui->max_volumes; i++) {
+		uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i],
+				     UBI_VTBL_RECORD_SIZE_CRC);
+		vtbl[i].crc = cpu_to_be32(crc);
 	}
 
-	write_vid_hdr(u, action);
-	rc = write_to_output_stream(u);
-	if (rc != 0)
-		return rc;
-
-	/* Update current handle */
-	u->bytes_read += read;
-	u->blks_written++;
-	return 0;
+	return vtbl;
 }
 
-int
-ubigen_write_complete(ubi_info_t u)
+/**
+ * ubigen_add_volume - add a volume to the volume table.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @vtbl: volume table to add to
+ *
+ * This function adds volume described by input parameters to the volume table
+ * @vtbl.
+ */
+int ubigen_add_volume(const struct ubigen_info *ui,
+		      const struct ubigen_vol_info *vi,
+		      struct ubi_vtbl_record *vtbl)
 {
-	size_t i;
-	int rc = 0;
-
-	for (i = 0; i < u->leb_total; i++) {
-		rc = ubigen_write_leb(u,  NO_ERROR);
-		if (rc != 0)
-			return rc;
-	}
-
+	struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
+	uint32_t tmp;
+
+	if (vi->id >= ui->max_volumes)
+		return errmsg("too high volume id %d, max. volumes is %d",
+			      vi->id, ui->max_volumes);
+
+	if (vi->alignment >= ui->leb_size)
+		return errmsg("too large alignment %d, max is %d (LEB size)",
+			      vi->alignment, ui->leb_size);
+
+	memset(vtbl_rec, '\0', sizeof(struct ubi_vtbl_record));
+	tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size;
+	vtbl_rec->reserved_pebs = cpu_to_be32(tmp);
+	vtbl_rec->alignment = cpu_to_be32(vi->alignment);
+	vtbl_rec->vol_type = vi->type;
+	tmp = ui->leb_size % vi->alignment;
+	vtbl_rec->data_pad = cpu_to_be32(tmp);
+	vtbl_rec->flags = vi->flags;
+
+	memcpy(vtbl_rec->name, vi->name, vi->name_len);
+	vtbl_rec->name[vi->name_len] = '\0';
+	vtbl_rec->name_len = cpu_to_be16(vi->name_len);
+
+	tmp = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
+	vtbl_rec->crc =	 cpu_to_be32(tmp);
 	return 0;
 }
 
-int
-ubigen_write_broken_update(ubi_info_t u, uint32_t blk)
+/**
+ * ubigen_init_ec_hdr - initialize EC header.
+ * @ui: libubigen information
+ * @hdr: the EC header to initialize
+ * @ec: erase counter value
+ */
+void ubigen_init_ec_hdr(const struct ubigen_info *ui,
+		        struct ubi_ec_hdr *hdr, long long ec)
 {
-	int rc = 0;
+	uint32_t crc;
 
-	rc = skip_blks(u, blk);
-	if (rc != 0)
-		return rc;
+	memset(hdr, '\0', sizeof(struct ubi_ec_hdr));
 
-	rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC);
-	if (rc != 0)
-		return rc;
+	hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
+	hdr->version = ui->ubi_ver;
+	hdr->ec = cpu_to_be64(ec);
+	hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs);
 
+	hdr->data_offset = cpu_to_be32(ui->data_offs);
 
-	return 0;
+	crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
 }
 
-void
-dump_info(ubi_info_t u ubi_unused)
+/**
+ * init_vid_hdr - initialize VID header.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @hdr: the VID header to initialize
+ * @lnum: logical eraseblock number
+ * @data: the contents of the LEB (static volumes only)
+ * @data_size: amount of data in this LEB (static volumes only)
+ *
+ * Note, @used_ebs, @data and @data_size are ignored in case of dynamic
+ * volumes.
+ */
+static void init_vid_hdr(const struct ubigen_info *ui,
+			 const struct ubigen_vol_info *vi,
+			 struct ubi_vid_hdr *hdr, int lnum,
+			 const void *data, int data_size)
 {
-#ifdef DEBUG
-	int err = 0;
-	if (!u) {
-		fprintf(stderr, "<empty>");
-		return;
-	}
-	if (!u->ec) {
-		fprintf(stderr, "<ec-empty>");
-		err = 1;
-	}
-	if (!u->v) {
-		fprintf(stderr, "<v-empty>");
-		err = 1;
-	}
-	if (err) return;
-
-	fprintf(stderr, "ubi volume\n");
-	fprintf(stderr, "version      :	  %8d\n", u->v->version);
-	fprintf(stderr, "vol_id	      :	  %8d\n", be32_to_cpu(u->v->vol_id));
-	fprintf(stderr, "vol_type     :	  %8s\n",
-		u->v->vol_type == UBI_VID_STATIC ?
-		"static" : "dynamic");
-	fprintf(stderr, "used_ebs     :	  %8d\n",
-		be32_to_cpu(u->v->used_ebs));
-	fprintf(stderr, "eb_size      : 0x%08x\n", u->eb_size);
-	fprintf(stderr, "leb_size     : 0x%08x\n", u->leb_size);
-	fprintf(stderr, "data_pad     : 0x%08x\n",
-		be32_to_cpu(u->v->data_pad));
-	fprintf(stderr, "leb_total    :	  %8d\n", u->leb_total);
-	fprintf(stderr, "header offs  : 0x%08x\n",
-		be32_to_cpu(u->ec->vid_hdr_offset));
-	fprintf(stderr, "bytes_total  :	  %8d\n", u->bytes_total);
-	fprintf(stderr, "  +  in MiB  : %8.2f M\n",
-		((float)(u->bytes_total)) / 1024 / 1024);
-	fprintf(stderr, "-------------------------------\n\n");
-#else
-	return;
-#endif
-}
+	uint32_t crc;
 
-int
-ubigen_destroy(ubi_info_t *u)
-{
-	if (u == NULL)
-		return -EINVAL;
-
-	ubi_info_t tmp = *u;
-
-	if (tmp) {
-		if (tmp->v)
-			free(tmp->v);
-		if (tmp->ec)
-			free(tmp->ec);
-		if (tmp->buf)
-			free(tmp->buf);
-		free(tmp);
+	memset(hdr, '\0', sizeof(struct ubi_vid_hdr));
+
+	hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
+	hdr->version = ui->ubi_ver;
+	hdr->vol_type = vi->type;
+	hdr->vol_id = cpu_to_be32(vi->id);
+	hdr->lnum = cpu_to_be32(lnum);
+	hdr->data_pad = cpu_to_be32(vi->data_pad);
+	hdr->compat = vi->compat;
+
+	if (vi->type == UBI_VID_STATIC) {
+		hdr->data_size = cpu_to_be32(data_size);
+		hdr->used_ebs = cpu_to_be32(vi->used_ebs);
+		crc = crc32(UBI_CRC32_INIT, data, data_size);
+		hdr->data_crc = cpu_to_be32(crc);
 	}
-	*u = NULL;
-	return 0;
-}
 
-void
-ubigen_init(void)
-{
-	init_crc32_table(crc32_table);
+	crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
 }
 
-int
-ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type,
-	      uint32_t eb_size, uint64_t ec, uint32_t alignment,
-	      uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag,
-	      size_t data_size, FILE* fp_in, FILE* fp_out)
+/**
+ * ubigen_write_volume - write UBI volume.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @ec: erase coutner value to put to EC headers
+ * @bytes: volume size in bytes
+ * @in: input file descriptor (has to be properly seeked)
+ * @out: output file descriptor
+ *
+ * This function reads the contents of the volume from the input file @in and
+ * writes the UBI volume to the output file @out. Returns zero on success and
+ * %-1 on failure.
+ */
+int ubigen_write_volume(const struct ubigen_info *ui,
+			const struct ubigen_vol_info *vi, long long ec,
+			long long bytes, int in, int out)
 {
-	int rc = 0;
-	ubi_info_t res = NULL;
-	uint32_t crc;
-	uint32_t data_offset;
+	int len = vi->usable_leb_size, rd, lnum = 0;
+	char inbuf[ui->leb_size], outbuf[ui->peb_size];
 
-	if (alignment == 0) {
-		rc = EUBIGEN_INVALID_ALIGNMENT;
-		goto ubigen_create_err;
-	}
-	if ((fp_in == NULL) || (fp_out == NULL)) {
-		rc = -EINVAL;
-		goto ubigen_create_err;
-	}
+	if (vi->id >= ui->max_volumes)
+		return errmsg("too high volume id %d, max. volumes is %d",
+			      vi->id, ui->max_volumes);
 
-	res = (ubi_info_t) calloc(1, sizeof(struct ubi_info));
-	if (res == NULL) {
-		rc = -ENOMEM;
-		goto ubigen_create_err;
-	}
+	if (vi->alignment >= ui->leb_size)
+		return errmsg("too large alignment %d, max is %d (LEB size)",
+			      vi->alignment, ui->leb_size);
 
-	res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr));
-	if (res->v == NULL) {
-		rc = -ENOMEM;
-		goto ubigen_create_err;
-	}
+	memset(outbuf, 0xFF, ui->data_offs);
+	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec);
 
-	res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr));
-	if (res->ec == NULL) {
-		rc = -ENOMEM;
-		goto ubigen_create_err;
-	}
+	while (bytes) {
+		int l;
+		struct ubi_vid_hdr *vid_hdr;
 
-	/* data which is needed in the general process */
-	vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET;
-	data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE;
-	res->bytes_total = data_size;
-	res->eb_size = eb_size ? eb_size : DEFAULT_BLOCKSIZE;
-	res->data_pad = (res->eb_size - data_offset) % alignment;
-	res->leb_size = res->eb_size - data_offset - res->data_pad;
-	res->leb_total = byte_to_blk(data_size, res->leb_size);
-	res->alignment = alignment;
-
-	if ((res->eb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) {
-		rc = EUBIGEN_TOO_SMALL_EB;
-		goto ubigen_create_err;
-	}
-	res->fp_in = fp_in;
-	res->fp_out = fp_out;
-
-	/* vid hdr data which doesn't change */
-	res->v->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
-	res->v->version = version ? version : UBI_VERSION;
-	res->v->vol_type = vol_type;
-	res->v->vol_id = cpu_to_be32(vol_id);
-	res->v->compat = compat_flag;
-	res->v->data_pad = cpu_to_be32(res->data_pad);
-
-	/* static only: used_ebs */
-	if (res->v->vol_type == UBI_VID_STATIC) {
-		res->v->used_ebs = cpu_to_be32(byte_to_blk
-						(res->bytes_total,
-						 res->leb_size));
-	}
+		if (bytes < len)
+			len = bytes;
+		bytes -= len;
 
-	/* ec hdr (fixed, doesn't change) */
-	res->ec->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
-	res->ec->version = version ? version : UBI_VERSION;
-	res->ec->ec = cpu_to_be64(ec);
-	res->ec->vid_hdr_offset = cpu_to_be32(vid_hdr_offset);
+		l = len;
+		do {
+			rd = read(in, inbuf + len - l, l);
+			if (rd != l)
+				return sys_errmsg("cannot read %d bytes from the input file", l);
 
-	res->ec->data_offset = cpu_to_be32(data_offset);
+			l -= rd;
+		} while (l);
 
-	crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec,
-			UBI_EC_HDR_SIZE_CRC);
-	res->ec->hdr_crc = cpu_to_be32(crc);
+		vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+		init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
 
-	/* prepare a read buffer */
-	res->buf = (uint8_t*) malloc (res->eb_size * sizeof(uint8_t));
-	if (res->buf == NULL) {
-		rc = -ENOMEM;
-		goto ubigen_create_err;
-	}
-
-	/* point to distinct regions within the buffer */
-	res->ptr_ec_hdr = res->buf;
-	res->ptr_vid_hdr = res->buf + be32_to_cpu(res->ec->vid_hdr_offset);
-	res->ptr_data = res->buf + be32_to_cpu(res->ec->vid_hdr_offset)
-		+ UBI_VID_HDR_SIZE;
+		memcpy(outbuf + ui->data_offs, inbuf, len);
+		memset(outbuf + ui->data_offs + len, 0xFF,
+		       ui->peb_size - ui->data_offs - len);
 
-	rc = validate_ubi_info(res);
-	if (rc != 0) {
-		fprintf(stderr, "Volume validation failed: %d\n", rc);
-		goto ubigen_create_err;
-	}
+		if (write(out, outbuf, ui->peb_size) != ui->peb_size)
+			return sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
 
-	dump_info(res);
-	*u = res;
-	return rc;
-
- ubigen_create_err:
-	if (res) {
-		if (res->v)
-			free(res->v);
-		if (res->ec)
-			free(res->ec);
-		if (res->buf)
-			free(res->buf);
-		free(res);
+		lnum += 1;
 	}
-	*u = NULL;
-	return rc;
-}
 
-int
-ubigen_get_leb_size(ubi_info_t u, size_t* size)
-{
-	if (u == NULL)
-		return -EINVAL;
-
-	*size = u->leb_size;
 	return 0;
 }
 
-
-int
-ubigen_get_leb_total(ubi_info_t u, size_t* total)
-{
-	if (u == NULL)
-		return -EINVAL;
-
-	*total = u->leb_total;
-	return 0;
-}
-
-int
-ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes,
-		    const char* vol_name, struct ubi_vtbl_record *lvol_rec)
+/**
+ * ubigen_write_layout_vol - write UBI layout volume
+ * @ui: libubigen information
+ * @peb1: physical eraseblock number to write the first volume table copy
+ * @peb2: physical eraseblock number to write the second volume table copy
+ * @ec1: erase counter value for @peb1
+ * @ec2: erase counter value for @peb1
+ * @vtbl: volume table
+ * @fd: output file descriptor seeked to the proper position
+ *
+ * This function creates the UBI layout volume which contains 2 copies of the
+ * volume table. Returns zero in case of success and %-1 in case of failure.
+ */
+int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
+			    long long ec1, long long ec2,
+			    struct ubi_vtbl_record *vtbl, int fd)
 {
-	uint32_t crc;
-
-	if ((u == NULL) || (vol_name == NULL))
-		return -EINVAL;
-
-	memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE);
-
-	lvol_rec->reserved_pebs =
-		cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size));
-	lvol_rec->alignment = cpu_to_be32(u->alignment);
-	lvol_rec->data_pad = u->v->data_pad;
-	lvol_rec->vol_type = u->v->vol_type;
-
-	lvol_rec->name_len =
-		cpu_to_be16((uint16_t)strlen((const char*)vol_name));
-
-	memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1);
-
-	crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
-			lvol_rec, UBI_VTBL_RECORD_SIZE_CRC);
-	lvol_rec->crc =	 cpu_to_be32(crc);
+	int ret;
+	struct ubigen_vol_info vi;
+	char outbuf[ui->peb_size];
+	struct ubi_vid_hdr *vid_hdr;
+	off_t seek;
+
+	vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
+	vi.id = UBI_LAYOUT_VOLUME_ID;
+	vi.alignment = UBI_LAYOUT_VOLUME_ALIGN;
+	vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
+	vi.usable_leb_size = ui->leb_size - vi.data_pad;
+	vi.data_pad = ui->leb_size - vi.usable_leb_size;
+	vi.type = UBI_LAYOUT_VOLUME_TYPE;
+	vi.name = UBI_LAYOUT_VOLUME_NAME;
+	vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
+	vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
+
+	memset(outbuf, 0xFF, ui->data_offs);
+	vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+	memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size);
+	memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF,
+	       ui->peb_size - ui->data_offs - ui->vtbl_size);
+
+	seek = peb1 * ui->peb_size;
+	if (lseek(fd, seek, SEEK_SET) != seek)
+		return sys_errmsg("cannot seek output file");
+	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1);
+	init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
+	ret = write(fd, outbuf, ui->peb_size);
+	if (ret != ui->peb_size)
+		return sys_errmsg("cannot write %d bytes", ui->peb_size);
+
+	seek = peb2 * ui->peb_size;
+	if (lseek(fd, seek, SEEK_SET) != seek)
+		return sys_errmsg("cannot seek output file");
+	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2);
+	init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
+	ret = write(fd, outbuf, ui->peb_size);
+	if (ret != ui->peb_size)
+		return sys_errmsg("cannot write %d bytes", ui->peb_size);
 
 	return 0;
 }
diff --git a/ubi-utils/src/libubimirror.c b/ubi-utils/src/libubimirror.c
deleted file mode 100644
index d06770e..0000000
--- a/ubi-utils/src/libubimirror.c
+++ /dev/null
@@ -1,237 +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.
- */
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <memory.h>
-#include <limits.h>
-#include <fcntl.h>
-
-#include <libubi.h>
-#include "ubimirror.h"
-
-#define COMPARE_BUF_SIZE    (128 * 1024)
-
-#define DEFAULT_DEV_PATTERN    "/dev/ubi%d"
-#define DEFAULT_VOL_PATTERN    "/dev/ubi%d_%d"
-
-#define EBUF(fmt...) do {			\
-	snprintf(err_buf, err_buf_size, fmt);	\
-} while (0)
-
-enum {
-	compare_error = -1,
-	seek_error = -2,
-	write_error = -3,
-	read_error = -4,
-	update_error = -5,
-	ubi_error = -6,
-	open_error = -7,
-	close_error = -8,
-	compare_equal = 0,
-	compare_different = 1
-};
-
-/*
- * Read len number of bytes from fd.
- * Return 0 on EOF, -1 on error.
- */
-static ssize_t fill_buffer(int fd, unsigned char *buf, ssize_t len)
-{
-	ssize_t got, have = 0;
-
-	do {
-		got = read(fd, buf + have, len - have);
-		if (got == -1 && errno != EINTR)
-			return -1;
-		have += got;
-	} while (got > 0 && have < len);
-	return have;
-}
-
-/*
- * Write len number of bytes to fd.
- * Return bytes written (>= 0), -1 on error.
- */
-static ssize_t flush_buffer(int fd, unsigned char *buf, ssize_t len)
-{
-	ssize_t done, have = 0;
-
-	do {
-		done = write(fd, buf + have, len - have);
-		if (done == -1 && errno != EINTR)
-			return -1;
-		have += done;
-	} while (done > 0 && have < len);
-	return have;
-}
-
-/*
- *  Compare two files.  Return 0, 1, or -1, depending on whether the
- *  files are equal, different, or an error occured.
- *  Return compare-different when target volume can not be read. Might be
- *  an interrupted volume update and then the target device returns -EIO but
- *  can be updated.
- *
- *  fd_a is source
- *  fd_b is destination
- */
-static int compare_files(int fd_a, int fd_b)
-{
-	unsigned char buf_a[COMPARE_BUF_SIZE], buf_b[COMPARE_BUF_SIZE];
-	ssize_t len_a, len_b;
-	int rc;
-
-	for (;;) {
-		len_a = fill_buffer(fd_a, buf_a, sizeof(buf_a));
-		if (len_a == -1) {
-			rc = compare_error;
-			break;
-		}
-		len_b = fill_buffer(fd_b, buf_b, sizeof(buf_b));
-		if (len_b == -1) {
-			rc = compare_different;
-			break;
-		}
-		if (len_a != len_b) {
-			rc = compare_different;
-			break;
-		}
-		if (len_a == 0) {	/* Size on both files equal and EOF */
-			rc = compare_equal;
-			break;
-		}
-		if (memcmp(buf_a, buf_b, len_a) != 0 ) {
-			rc = compare_different;
-			break;
-		}
-	}
-	/* Position both files at the beginning */
-	if (lseek(fd_a, 0, SEEK_SET) == -1 ||
-	   lseek(fd_b, 0, SEEK_SET) == -1)
-		rc = seek_error;
-	return rc;
-}
-
-int vol_get_used_bytes(int vol_fd, unsigned long long *bytes)
-{
-	off_t res;
-
-	res = lseek(vol_fd, 0, SEEK_END);
-	if (res == (off_t)-1)
-		return -1;
-	*bytes = (unsigned long long) res;
-	res = lseek(vol_fd, 0, SEEK_SET);
-	return res == (off_t)-1 ? -1 : 0;
-}
-
-static int copy_files(libubi_t ulib, int fd_in, int fd_out)
-{
-	unsigned char buf_a[COMPARE_BUF_SIZE];
-	ssize_t len_a, len_b;
-	unsigned long long update_size, copied;
-
-	if (vol_get_used_bytes(fd_in, &update_size) == -1 ||
-	    ubi_update_start(ulib, fd_out, update_size) == -1)
-		return update_error;
-	for (copied = 0; copied < update_size; copied += len_b ) {
-		len_a = fill_buffer(fd_in, buf_a, sizeof(buf_a));
-		if (len_a == -1)
-			return read_error;
-		if (len_a == 0)		/* Reach EOF */
-			return 0;
-		len_b = flush_buffer(fd_out, buf_a, len_a);
-		if (len_b != len_a)
-			return write_error;
-	}
-	return 0;
-}
-
-int ubimirror(uint32_t devno, int seqnum, uint32_t *ids, ssize_t ids_size,
-		char *err_buf, size_t err_buf_size)
-{
-	int rc = 0;
-	uint32_t src_id;
-	char path[PATH_MAX];
-	libubi_t ulib;
-	int fd_in = -1, i = 0, fd_out = -1;
-
-	if (ids_size == 0)
-		return 0;
-	else {
-		if ((seqnum < 0) || (seqnum > (ids_size - 1))) {
-			EBUF("volume id %d out of range", seqnum);
-			return EUBIMIRROR_NO_SRC;
-		}
-		src_id = ids[seqnum];
-	}
-
-	ulib = libubi_open();
-	if (ulib == NULL)
-		return ubi_error;
-
-	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, src_id);
-
-	fd_in = open(path, O_RDONLY);
-	if (fd_in == -1) {
-		EBUF("open error source volume %d", ids[i]);
-		rc = open_error;
-		goto err;
-	}
-
-	for (i = 0; i < ids_size; i++) {
-		if (ids[i] == src_id)		/* skip self-mirror */
-			continue;
-
-		snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, ids[i]);
-
-		fd_out = open(path, O_RDWR);
-		if (fd_out < 0){
-			EBUF("open error destination volume %d", ids[i]);
-			rc = open_error;
-			goto err;
-		}
-		rc = compare_files(fd_in, fd_out);
-		if (rc < 0) {
-			EBUF("compare error volume %d and %d", src_id, ids[i]);
-			goto err;
-		} else if (rc == compare_different) {
-			rc = copy_files(ulib, fd_in, fd_out);
-			if (rc != 0) {
-				EBUF("mirror error volume %d to %d", src_id,
-						ids[i]);
-				goto err;
-			}
-		}
-		if ((rc = close(fd_out)) == -1) {
-			EBUF("close error volume %d", ids[i]);
-			rc = close_error;
-			goto err;
-		} else
-			fd_out = -1;
-	}
-err:
-	if (fd_out != -1)
-		close(fd_out);
-	if (fd_in != -1)
-		close(fd_in);
-	if (ulib != NULL)
-		libubi_close(ulib);
-	return rc;
-}
diff --git a/ubi-utils/src/list.c b/ubi-utils/src/list.c
deleted file mode 100644
index 6eb716b..0000000
--- a/ubi-utils/src/list.c
+++ /dev/null
@@ -1,149 +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
- */
-
-#include <stdlib.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "list.h"
-
-list_t
-mk_empty(void)
-{
-	return (list_t) NULL;
-}
-
-int
-is_empty(list_t l)
-{
-	return l == NULL;
-}
-
-info_t
-head(list_t l)
-{
-	assert(!is_empty(l));
-	return l->info;
-}
-
-list_t
-tail(list_t l)
-{
-	assert(!is_empty(l));
-	return l->next;
-}
-
-list_t
-remove_head(list_t l)
-{
-	list_t res;
-	assert(!is_empty(l));
-
-	res = l->next;
-	free(l);
-	return res;
-}
-
-list_t
-cons(info_t e, list_t l)
-{
-	list_t res = malloc(sizeof(*l));
-	if (!res)
-		return NULL;
-	res->info = e;
-	res->next = l;
-
-	return res;
-}
-
-list_t
-prepend_elem(info_t e, list_t l)
-{
-	return cons(e,l);
-}
-
-list_t
-append_elem(info_t e, list_t l)
-{
-	if (is_empty(l)) {
-		return cons(e,l);
-	}
-	l->next = append_elem(e, l->next);
-
-	return l;
-}
-
-list_t
-insert_sorted(cmp_func_t cmp, info_t e, list_t l)
-{
-	if (is_empty(l))
-		return cons(e, l);
-
-	switch (cmp(e, l->info)) {
-	case -1:
-	case  0:
-		return l;
-		break;
-	case  1:
-		l->next = insert_sorted(cmp, e, l);
-		break;
-	default:
-		break;
-	}
-
-	/* never reached */
-	return NULL;
-}
-
-list_t
-remove_all(free_func_t free_func, list_t l)
-{
-	if (is_empty(l))
-		return l;
-	list_t lnext = l->next;
-
-	if (free_func && l->info) {
-		free_func(&(l->info));
-	}
-	free(l);
-
-	return remove_all(free_func, lnext);
-}
-
-
-info_t
-is_in(cmp_func_t cmp, info_t e, list_t l)
-{
-	return
-	(is_empty(l))
-	? NULL
-	: (cmp(e, l->info)) == 0 ? l->info : is_in(cmp, e, l->next);
-}
-
-
-void
-apply(process_func_t process_func, list_t l)
-{
-	list_t ptr;
-	void *i;
-	foreach(i, ptr, l) {
-		process_func(i);
-	}
-}
diff --git a/ubi-utils/src/list.h b/ubi-utils/src/list.h
deleted file mode 100644
index e8452a2..0000000
--- a/ubi-utils/src/list.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef __LIST_H__
-#define __LIST_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: Oliver Lohmann
- */
-
-#include <stdint.h>
-
-#define foreach(elem, ptr, list)				\
-	for (elem = list != NULL ? (typeof(elem)) head(list)	\
-				 : NULL, ptr = list;		\
-		ptr != NULL;					\
-		ptr = tail(ptr),				\
-		elem = (typeof(elem)) ptr ? head(ptr) : NULL)
-
-typedef struct node* list_t;
-typedef void* info_t;
-typedef int  (*free_func_t)(info_t*);
-typedef int  (*cmp_func_t)(info_t, info_t);
-typedef void (*process_func_t)(info_t);
-
-struct node {
-	list_t next;
-	info_t	info;
-};
-
-list_t mk_empty(void);
-int    is_empty(list_t l);
-info_t is_in(cmp_func_t cmp, info_t e, list_t l);
-info_t head(list_t l);
-list_t tail(list_t l);
-list_t remove_head(list_t l);
-list_t cons(info_t e, list_t l);
-list_t prepend_elem(info_t e, list_t);
-list_t append_elem(info_t e, list_t);
-list_t remove_all(free_func_t free_func, list_t l);
-list_t insert_sorted(cmp_func_t cmp_func, info_t e, list_t l);
-void   apply(process_func_t process_func, list_t l);
-
-#endif /* __LIST_H__ */
diff --git a/ubi-utils/src/mkbootenv.c b/ubi-utils/src/mkbootenv.c
deleted file mode 100644
index 50fc8ac..0000000
--- a/ubi-utils/src/mkbootenv.c
+++ /dev/null
@@ -1,168 +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
- *
- * Create boot-parameter/pdd data from an ASCII-text input file.
- *
- * 1.2 Removed argp because we want to use uClibc.
- * 1.3 Minor cleanup
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <errno.h>
-#include <mtd/ubi-media.h>
-
-#include "config.h"
-#include "bootenv.h"
-#include "error.h"
-
-#define PROGRAM_VERSION "1.3"
-
-static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
-	"mkbootenv - processes bootenv text files and convertes "
-	"them into a binary format.\n";
-
-static const char copyright [] __attribute__((unused)) =
-	"Copyright (c) International Business Machines Corp., 2006";
-
-static const char *optionsstr =
-"  -c, --copyright          Print copyright informatoin.\n"
-"  -o, --output=<fname>     Write the output data to <output> instead of\n"
-"                           stdout.\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: mkbootenv [-c?V] [-o <output>] [--copyright] [--output=<output>]\n"
-"            [--help] [--usage] [--version] [bootenv-txt-file]\n";
-
-struct option long_options[] = {
-	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
-	{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
-	{ .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}
-};
-
-typedef struct myargs {
-	FILE* fp_in;
-	FILE* fp_out;
-
-	char *arg1;
-	char **options;			/* [STRING...] */
-} myargs;
-
-static int
-parse_opt(int argc, char **argv, myargs *args)
-{
-	while (1) {
-		int key;
-
-		key = getopt_long(argc, argv, "co:?V", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-			case 'c':
-				fprintf(stderr, "%s\n", copyright);
-				exit(0);
-				break;
-			case 'o':
-				args->fp_out = fopen(optarg, "wb");
-				if ((args->fp_out) == NULL) {
-					fprintf(stderr, "Cannot open file %s "
-						"for output\n", optarg);
-					exit(1);
-				}
-				break;
-			case '?': /* help */
-				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);
-		}
-	}
-
-	if (optind < argc) {
-		args->fp_in = fopen(argv[optind++], "rb");
-		if ((args->fp_in) == NULL) {
-			fprintf(stderr,	"Cannot open file %s for input\n",
-				argv[optind]);
-			exit(1);
-		}
-	}
-
-	return 0;
-}
-
-int
-main(int argc, char **argv) {
-	int rc = 0;
-	bootenv_t env;
-
-	myargs args = {
-		.fp_in = stdin,
-		.fp_out = stdout,
-		.arg1 = NULL,
-		.options = NULL,
-	};
-
-	parse_opt(argc, argv, &args);
-
-	rc = bootenv_create(&env);
-	if (rc != 0) {
-		err_msg("Cannot create bootenv handle.");
-		goto err;
-	}
-	rc = bootenv_read_txt(args.fp_in, env);
-	if (rc != 0) {
-		err_msg("Cannot read bootenv from input file.");
-		goto err;
-	}
-	rc = bootenv_write(args.fp_out, env);
-	if (rc != 0) {
-		err_msg("Cannot write bootenv to output file.");
-		goto err;
-	}
-
-	if (args.fp_in != stdin) {
-		fclose(args.fp_in);
-	}
-	if (args.fp_out != stdout) {
-		fclose(args.fp_out);
-	}
-
-err:
-	bootenv_destroy(&env);
-	return rc;
-}
diff --git a/ubi-utils/src/nand2bin.c b/ubi-utils/src/nand2bin.c
deleted file mode 100644
index 93ba29f..0000000
--- a/ubi-utils/src/nand2bin.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006, 2007
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Frank Haverkamp
- *
- * An utility to decompose NAND images and strip OOB off. Not yet finished ...
- *
- * 1.2 Removed argp because we want to use uClibc.
- * 1.3 Minor cleanup
- * 1.4 Fixed OOB output file
- * 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.
- */
-
-#include <config.h>
-#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/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "config.h"
-#include "nandecc.h"
-
-#define PROGRAM_VERSION "1.6"
-
-#define MAXPATH		1024
-#define MIN(x,y)	((x)<(y)?(x):(y))
-
-struct args {
-	const char *oob_file;
-	const char *output_file;
-	size_t pagesize;
-	size_t blocksize;
-	int split_blocks;
-	size_t in_len;		/* size of input file */
-	int correct_ecc;
-
-	/* special stuff needed to get additional arguments */
-	char *arg1;
-	char **options;		/* [STRING...] */
-};
-
-static struct args myargs = {
-	.output_file = "data.bin",
-	.oob_file = "oob.bin",
-	.pagesize = 2048,
-	.blocksize = 128 * 1024,
-	.in_len = 0,
-	.split_blocks = 0,
-	.correct_ecc = 0,
-	.arg1 = NULL,
-	.options = NULL,
-};
-
-static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
-	"nand2bin - split data and OOB.\n";
-
-static const char *optionsstr =
-"  -o, --output=<output>      Data output file\n"
-"  -O, --oob=<oob>            OOB output file\n"
-"  -p, --pagesize=<pagesize>  NAND pagesize\n"
-"  -b, --blocksize=<blocksize> NAND blocksize\n"
-"  -s, --split-blocks         generate binaries for each block\n"
-"  -e, --correct-ecc          Correct data according to ECC info\n"
-"  -v, --verbose              verbose output\n"
-"  -?, --help                 Give this help list\n"
-"      --usage                Give a short usage message\n";
-
-static const char *usage =
-"Usage: nand2bin [-?] [-o <output>] [-O <oob>] [-p <pagesize>]\n"
-"          [--output=<output>] [--oob=<oob>] [--pagesize=<pagesize>] [--help]\n"
-"          [--usage] input.mif\n";
-
-static int verbose = 0;
-
-static struct option long_options[] = {
-	{ .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' },
-	{ .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'b' },
-	{ .name = "split-blocks", .has_arg = 0, .flag = NULL, .val = 's' },
-	{ .name = "correct-ecc", .has_arg = 0, .flag = NULL, .val = 'e' },
-	{ .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
-	{ .name = "help", .has_arg = 0, .flag = NULL, .val = '?' },
-	{ .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 },
-	{ NULL, 0, NULL, 0}
-};
-
-/*
- * str_to_num - Convert string into number and cope with endings like
- *              k, K, kib, KiB for kilobyte
- *              m, M, mib, MiB for megabyte
- */
-static uint32_t str_to_num(char *str)
-{
-	char *s = str;
-	ulong num = strtoul(s, &s, 0);
-
-	if (*s != '\0') {
-		if (strcmp(s, "KiB") == 0)
-			num *= 1024;
-		else if (strcmp(s, "MiB") == 0)
-			num *= 1024*1024;
-		else {
-			fprintf(stderr, "WARNING: Wrong number format "
-				"\"%s\", check your paramters!\n", str);
-		}
-	}
-	return num;
-}
-
-/*
- * @brief Parse the arguments passed into the test case.
- *
- * @param argc           The number of arguments
- * @param argv           The argument list
- * @param args           Pointer to program args structure
- *
- * @return error
- *
- */
-static int parse_opt(int argc, char **argv, struct args *args)
-{
-	while (1) {
-		int key;
-
-		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 'o': /* --output=<output.bin> */
-			args->output_file = optarg;
-			break;
-
-		case 'O': /* --oob=<oob.bin> */
-			args->oob_file = optarg;
-			break;
-
-		case '?': /* help */
-			printf("Usage: nand2bin [OPTION...] input.mif\n");
-			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);
-		}
-	}
-
-	if (optind < argc)
-		args->arg1 = argv[optind++];
-
-	return 0;
-}
-
-static int calc_oobsize(size_t pagesize)
-{
-	switch (pagesize) {
-	case 512:  return 16;
-	case 2048: return 64;
-	default:
-		exit(EXIT_FAILURE);
-	}
-	return 0;
-}
-
-static inline void hexdump(FILE *fp, const uint8_t *buf, ssize_t size)
-{
-	int k;
-
-	for (k = 0; k < size; k++) {
-		fprintf(fp, "%02x ", buf[k]);
-		if ((k & 15) == 15)
-			fprintf(fp, "\n");
-	}
-}
-
-static int process_page(uint8_t* buf, uint8_t *oobbuf, size_t pagesize)
-{
-	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)
-{
-	int read, rc, page = 0;
-	size_t oobsize = calc_oobsize(args->pagesize);
-	uint8_t *buf = malloc(args->pagesize);
-	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 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)
-		exit(EXIT_FAILURE);
-	if (!oob)
-		exit(EXIT_FAILURE);
-	if (!calc_oob)
-		exit(EXIT_FAILURE);
-	if (!calc_buf)
-		exit(EXIT_FAILURE);
-
-	while (!feof(in_fp)) {
-		/* read page by page */
-		read = fread(buf, 1, args->pagesize, in_fp);
-		if (ferror(in_fp)) {
-			fprintf(stderr, "I/O Error.");
-			exit(EXIT_FAILURE);
-		}
-		if (read != (ssize_t)args->pagesize)
-			break;
-
-		read = fread(oob, 1, oobsize, in_fp);
-		if (ferror(in_fp)) {
-			fprintf(stderr, "I/O Error.");
-			exit(EXIT_FAILURE);
-		}
-
-		page_buf = buf;	/* default is unmodified data */
-
-		if ((page == 0 || page == 1) && (oob[badpos] != 0xff)) {
-			if (verbose)
-				printf("Block %d is bad\n",
-				       page / pages_per_block);
-			goto write_data;
-		}
-		if (args->correct_ecc)
-			page_buf = calc_buf;
-
-		process_page(buf, calc_oob, args->pagesize);
-		memcpy(calc_buf, buf, args->pagesize);
-
-		/*
-		 * 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, oobsize);
-
-			printf("Calculated OOB Data:\n");
-			hexdump(stdout, calc_oob, oobsize);
-		}
-
-		/* Do correction on subpage base */
-		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",
-					page / pages_per_block,
-					page % pages_per_block, i / 256);
-			else if (rc > 0)
-				fprintf(stdout, "Correctable ECC error at "
-					"block %d page %d/%d\n",
-					page / pages_per_block,
-					page % pages_per_block, i / 256);
-		}
-
-	write_data:
-		rc = fwrite(page_buf, 1, args->pagesize, bin_fp);
-		if (ferror(bin_fp)) {
-			fprintf(stderr, "I/O Error.");
-			exit(EXIT_FAILURE);
-		}
-		rc = fwrite(oob, 1, oobsize, oob_fp);
-		if (ferror(bin_fp)) {
-			fprintf(stderr, "I/O Error.");
-			exit(EXIT_FAILURE);
-		}
-
-		page++;
-	}
-	free(calc_buf);
-	free(calc_oob);
-	free(oob);
-	free(buf);
-	return 0;
-}
-
-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 + oobsize);
-	int blocks = args->in_len / block_len;
-	char bname[256] = { 0, };
-	int badpos = bad_marker_offs_in_oob(args->pagesize);
-	int bad_blocks = 0, i, bad_block = 0;
-	ssize_t rc;
-	FILE *b;
-
-	buf = malloc(block_len);
-	if (!buf) {
-		perror("Not enough memory");
-		exit(EXIT_FAILURE);
-	}
-
-	for (i = 0; i < blocks; i++) {
-		rc = fread(buf, 1, block_len, in_fp);
-		if (rc != block_len) {
-			fprintf(stderr, "cannot read enough data!\n");
-			exit(EXIT_FAILURE);
-		}
-
-		/* do block analysis */
-		bad_block = 0;
-		if ((buf[args->pagesize + 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, oobsize);
-			printf("--\n");
-			hexdump(stdout, buf + 2 * args->pagesize +
-				oobsize, oobsize);
-		}
-
-		/* write complete block out */
-		snprintf(bname, sizeof(bname) - 1, "%s.%d", args->arg1, i);
-		b = fopen(bname, "w+");
-		if (!b) {
-			perror("Cannot open file");
-			exit(EXIT_FAILURE);
-		}
-		rc = fwrite(buf, 1, block_len, b);
-		if (rc != block_len) {
-			fprintf(stderr, "could not write all data!\n");
-			exit(EXIT_FAILURE);
-		}
-		fclose(b);
-	}
-
-	free(buf);
-	if (bad_blocks || verbose)
-		fprintf(stderr, "%d blocks, %d bad blocks\n",
-			blocks, bad_blocks);
-	return 0;
-}
-
-int
-main(int argc, char *argv[])
-{
-	FILE *in, *bin = NULL, *oob = NULL;
-	struct stat file_info;
-
-	parse_opt(argc, argv, &myargs);
-
-	if (!myargs.arg1) {
-		fprintf(stderr, "Please specify input file!\n");
-		exit(EXIT_FAILURE);
-	}
-
-	if (stat(myargs.arg1, &file_info) != 0) {
-		perror("Cannot fetch file size from input file.\n");
-		exit(EXIT_FAILURE);
-	}
-	myargs.in_len = file_info.st_size;
-
-	in = fopen(myargs.arg1, "r");
-	if (!in) {
-		perror("Cannot open file");
-		exit(EXIT_FAILURE);
-	}
-
-	if (myargs.split_blocks) {
-		split_blocks(&myargs, in);
-		goto out;
-	}
-
-	bin = fopen(myargs.output_file, "w+");
-	if (!bin) {
-		perror("Cannot open file");
-		exit(EXIT_FAILURE);
-	}
-	oob = fopen(myargs.oob_file, "w+");
-	if (!oob) {
-		perror("Cannot open file");
-		exit(EXIT_FAILURE);
-	}
-	decompose_image(&myargs, in, bin, oob);
-
- out:
-	if (in)	 fclose(in);
-	if (bin) fclose(bin);
-	if (oob) fclose(oob);
-	exit(EXIT_SUCCESS);
-}
diff --git a/ubi-utils/src/nandcorr.c b/ubi-utils/src/nandcorr.c
deleted file mode 100644
index caa07e2..0000000
--- a/ubi-utils/src/nandcorr.c
+++ /dev/null
@@ -1,95 +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.
- */
-
-/*
- * ECC algorithm for NAND FLASH. Detects and corrects 1 bit errors in
- * a 256 bytes of data.
- *
- * Reimplement by Thomas Gleixner after staring long enough at the
- * mess in drivers/mtd/nand/nandecc.c
- *
- */
-
-#include "nandecc.h"
-
-static int countbits(uint32_t byte)
-{
-	int res = 0;
-
-	for (;byte; byte >>= 1)
-		res += byte & 0x01;
-	return res;
-}
-
-/**
- * @dat:       data which should be corrected
- * @read_ecc:  ecc information read from flash
- * @calc_ecc:  calculated ecc information from the data
- * @return:    number of corrected bytes
- *             or -1 when no correction is possible
- */
-int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc,
-		      const uint8_t *calc_ecc)
-{
-	uint8_t s0, s1, s2;
-
-	/*
-	 * Do error detection
-	 *
-	 * Be careful, the index magic is due to a pointer to a
-	 * uint32_t.
-	 */
-	s0 = calc_ecc[0] ^ read_ecc[0];
-	s1 = calc_ecc[1] ^ read_ecc[1];
-	s2 = calc_ecc[2] ^ read_ecc[2];
-
-	if ((s0 | s1 | s2) == 0)
-		return 0;
-
-	/* Check for a single bit error */
-	if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
-	    ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
-	    ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
-
-		uint32_t byteoffs, bitnum;
-
-		byteoffs = (s1 << 0) & 0x80;
-		byteoffs |= (s1 << 1) & 0x40;
-		byteoffs |= (s1 << 2) & 0x20;
-		byteoffs |= (s1 << 3) & 0x10;
-
-		byteoffs |= (s0 >> 4) & 0x08;
-		byteoffs |= (s0 >> 3) & 0x04;
-		byteoffs |= (s0 >> 2) & 0x02;
-		byteoffs |= (s0 >> 1) & 0x01;
-
-		bitnum = (s2 >> 5) & 0x04;
-		bitnum |= (s2 >> 4) & 0x02;
-		bitnum |= (s2 >> 3) & 0x01;
-
-		dat[byteoffs] ^= (1 << bitnum);
-
-		return 1;
-	}
-
-	if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
-		return 1;
-
-	return -1;
-}
-
diff --git a/ubi-utils/src/nandecc.c b/ubi-utils/src/nandecc.c
deleted file mode 100644
index 71660ef..0000000
--- a/ubi-utils/src/nandecc.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * This file contains an ECC algorithm from Toshiba that detects and
- * corrects 1 bit errors in a 256 byte block of data.
- *
- * drivers/mtd/nand/nand_ecc.c
- *
- * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
- *			   Toshiba America Electronics Components, Inc.
- *
- * This file 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 or (at your option) any
- * later version.
- *
- * This file 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 file; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * As a special exception, if other files instantiate templates or use
- * macros or inline functions from these files, or you compile these
- * files and link them with other works to produce a work based on these
- * files, these files do not by themselves cause the resulting work to be
- * covered by the GNU General Public License. However the source code for
- * these files must still be made available in accordance with section (3)
- * of the GNU General Public License.
- *
- * This exception does not invalidate any other reasons why a work based on
- * this file might be covered by the GNU General Public License.
- */
-
-#include "nandecc.h"
-
-/*
- * Pre-calculated 256-way 1 byte column parity
- */
-static const uint8_t nand_ecc_precalc_table[] = {
-	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
-	0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
-	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
-	0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
-	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
-	0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
-	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
-	0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
-	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
-	0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
-	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
-	0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
-	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
-	0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
-	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
-	0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
-	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
-	0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
-	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
-	0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
-	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
-	0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
-	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
-	0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
-	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
-	0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
-	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
-	0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
-	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
-	0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
-	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
-	0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
-};
-
-/**
- * nand_trans_result - [GENERIC] create non-inverted ECC
- * @reg2:	line parity reg 2
- * @reg3:	line parity reg 3
- * @ecc_code:	ecc
- *
- * Creates non-inverted ECC code from line parity
- */
-static void nand_trans_result(uint8_t reg2, uint8_t reg3,
-	uint8_t *ecc_code)
-{
-	uint8_t a, b, i, tmp1, tmp2;
-
-	/* Initialize variables */
-	a = b = 0x80;
-	tmp1 = tmp2 = 0;
-
-	/* Calculate first ECC byte */
-	for (i = 0; i < 4; i++) {
-		if (reg3 & a)		/* LP15,13,11,9 --> ecc_code[0] */
-			tmp1 |= b;
-		b >>= 1;
-		if (reg2 & a)		/* LP14,12,10,8 --> ecc_code[0] */
-			tmp1 |= b;
-		b >>= 1;
-		a >>= 1;
-	}
-
-	/* Calculate second ECC byte */
-	b = 0x80;
-	for (i = 0; i < 4; i++) {
-		if (reg3 & a)		/* LP7,5,3,1 --> ecc_code[1] */
-			tmp2 |= b;
-		b >>= 1;
-		if (reg2 & a)		/* LP6,4,2,0 --> ecc_code[1] */
-			tmp2 |= b;
-		b >>= 1;
-		a >>= 1;
-	}
-
-	/* Store two of the ECC bytes */
-	ecc_code[1] = tmp1;
-	ecc_code[0] = tmp2;
-}
-
-/**
- * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for
- * 256 byte block
- *
- * @dat:	raw data
- * @ecc_code:	buffer for ECC
- */
-int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code)
-{
-	uint8_t idx, reg1, reg2, reg3;
-	int j;
-
-	/* Initialize variables */
-	reg1 = reg2 = reg3 = 0;
-	ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
-
-	/* Build up column parity */
-	for(j = 0; j < 256; j++) {
-
-		/* Get CP0 - CP5 from table */
-		idx = nand_ecc_precalc_table[dat[j]];
-		reg1 ^= (idx & 0x3f);
-
-		/* All bit XOR = 1 ? */
-		if (idx & 0x40) {
-			reg3 ^= (uint8_t) j;
-			reg2 ^= ~((uint8_t) j);
-		}
-	}
-
-	/* Create non-inverted ECC code from line parity */
-	nand_trans_result(reg2, reg3, ecc_code);
-
-	/* Calculate final ECC code */
-	ecc_code[0] = ~ecc_code[0];
-	ecc_code[1] = ~ecc_code[1];
-	ecc_code[2] = ((~reg1) << 2) | 0x03;
-	return 0;
-}
diff --git a/ubi-utils/src/nandecc.h b/ubi-utils/src/nandecc.h
deleted file mode 100644
index bcf1982..0000000
--- a/ubi-utils/src/nandecc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _NAND_ECC_H
-#define _NAND_ECC_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.
- *
- * NAND ecc functions
- */
-
-#include <stdint.h>
-
-int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code);
-int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc,
-		      const uint8_t *calc_ecc);
-
-#endif
diff --git a/ubi-utils/src/pddcustomize.c b/ubi-utils/src/pddcustomize.c
deleted file mode 100644
index 1eb9b9a..0000000
--- a/ubi-utils/src/pddcustomize.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2008
- *
- * 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
- *
- * PDD (platform description data) contains a set of system specific
- * boot-parameters. Some of those parameters need to be handled
- * special on updates, e.g. the MAC addresses. They must also be kept
- * if the system is updated and one must be able to modify them when
- * the system has booted the first time. This tool is intended to do
- * PDD modification.
- *
- * 1.3 Removed argp because we want to use uClibc.
- * 1.4 Minor cleanups
- * 1.5 Migrated to new libubi
- * 1.6 Fixed broken volume update
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-#include <mtd/ubi-media.h>
-
-#include "config.h"
-#include "bootenv.h"
-#include "error.h"
-#include "example_ubi.h"
-#include "libubi.h"
-#include "ubimirror.h"
-
-#define PROGRAM_VERSION "1.6"
-
-#define DEFAULT_DEV_PATTERN    "/dev/ubi%d"
-#define DEFAULT_VOL_PATTERN    "/dev/ubi%d_%d"
-
-typedef enum action_t {
-	ACT_NORMAL   = 0,
-	ACT_LIST,
-	ACT_ARGP_ABORT,
-	ACT_ARGP_ERR,
-} action_t;
-
-#define ABORT_ARGP do {			\
-	args->action = ACT_ARGP_ABORT;	\
-} while (0)
-
-#define ERR_ARGP do {			\
-	args->action = ACT_ARGP_ERR;	\
-} while (0)
-
-static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
-	"pddcustomize - customize bootenv and pdd values.\n";
-
-static const char *optionsstr =
-"  -b, --both                 Mirror updated PDD to redundand copy.\n"
-"  -c, --copyright            Print copyright information.\n"
-"  -i, --input=<input>        Binary input file. For debug purposes.\n"
-"  -l, --list                 List card bootenv/pdd values.\n"
-"  -o, --output=<output>      Binary output file. For debug purposes.\n"
-"  -s, --side=<seqnum>        The side/seqnum to update.\n"
-"  -x, --host                 use x86 platform for debugging.\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: pddcustomize [-bclx?V] [-i <input>] [-o <output>] [-s <seqnum>]\n"
-"           [--both] [--copyright] [--input=<input>] [--list]\n"
-"           [--output=<output>] [--side=<seqnum>] [--host] [--help] [--usage]\n"
-"           [--version] [key=value] [...]\n";
-
-struct option long_options[] = {
-	{ .name = "both", .has_arg = 0, .flag = NULL, .val = 'b' },
-	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
-	{ .name = "input", .has_arg = 1, .flag = NULL, .val = 'i' },
-	{ .name = "list", .has_arg = 0, .flag = NULL, .val = 'l' },
-	{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
-	{ .name = "side", .has_arg = 1, .flag = NULL, .val = 's' },
-	{ .name = "host", .has_arg = 0, .flag = NULL, .val = 'x' },
-	{ .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}
-};
-
-static const char copyright [] __attribute__((unused)) =
-	"Copyright IBM Corp 2006";
-
-typedef struct myargs {
-	action_t action;
-	const char* file_in;
-	const char* file_out;
-	int both;
-	int side;
-	int x86;		/* X86 host, use files for testing */
-	bootenv_t env_in;
-
-	char *arg1;
-	char **options;		/* [STRING...] */
-} myargs;
-
-static int
-get_update_side(const char* str)
-{
-	uint32_t i = strtoul(str, NULL, 0);
-
-	if ((i != 0) && (i != 1)) {
-		return -1;
-	}
-
-	return i;
-}
-
-static int
-extract_pair(bootenv_t env, const char* str)
-{
-	int rc = 0;
-	char* key;
-	char* val;
-
-	key = strdup(str);
-	if (key == NULL)
-		return -ENOMEM;
-
-	val = strstr(key, "=");
-	if (val == NULL) {
-		err_msg("Wrong argument: %s\n"
-			"Expecting key=value pair.\n", str);
-		rc = -1;
-		goto err;
-	}
-
-	*val = '\0'; /* split strings */
-	val++;
-	rc = bootenv_set(env, key, val);
-
-err:
-	free(key);
-	return rc;
-}
-
-static int
-parse_opt(int argc, char **argv, myargs *args)
-{
-	int rc = 0;
-
-	while (1) {
-		int key;
-
-		key = getopt_long(argc, argv, "clbxs:i:o:?V",
-				  long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-			case 'c':
-				err_msg("%s\n", copyright);
-				ABORT_ARGP;
-				break;
-			case 'l':
-				args->action = ACT_LIST;
-				break;
-			case 'b':
-				args->both = 1;
-				break;
-			case 'x':
-				args->x86 = 1;
-				break;
-			case 's':
-				args->side = get_update_side(optarg);
-				if (args->side < 0) {
-					err_msg("Unsupported seqnum: %d.\n"
-						"Supported seqnums are "
-						"'0' and '1'\n",
-						args->side, optarg);
-					ERR_ARGP;
-				}
-				break;
-			case 'i':
-				args->file_in = optarg;
-				break;
-			case 'o':
-				args->file_out = optarg;
-				break;
-			case '?': /* help */
-				err_msg("Usage: pddcustomize [OPTION...] "
-					"[key=value] [...]");
-				err_msg("%s", doc);
-				err_msg("%s", optionsstr);
-				err_msg("\nReport bugs to %s",
-					PACKAGE_BUGREPORT);
-				exit(0);
-				break;
-			case 'V':
-				err_msg("%s", PROGRAM_VERSION);
-				exit(0);
-				break;
-			default:
-				err_msg("%s", usage);
-				exit(-1);
-		}
-	}
-
-	if (optind < argc) {
-		rc = extract_pair(args->env_in, argv[optind++]);
-		if (rc != 0)
-			ERR_ARGP;
-	}
-
-	return 0;
-}
-
-static int
-list_bootenv(bootenv_t env)
-{
-	int rc = 0;
-	rc = bootenv_write_txt(stdout, env);
-	if (rc != 0) {
-		err_msg("Cannot list bootenv/pdd. rc: %d\n", rc);
-		goto err;
-	}
-err:
-	return rc;
-}
-
-static int
-process_key_value(bootenv_t env_in, bootenv_t env)
-{
-	int rc = 0;
-	size_t size, i;
-	const char* tmp;
-	const char** key_vec = NULL;
-
-	rc = bootenv_get_key_vector(env_in, &size, 0, &key_vec);
-	if (rc != 0)
-		goto err;
-
-	for (i = 0; i < size; i++) {
-		rc = bootenv_get(env_in, key_vec[i], &tmp);
-		if (rc != 0) {
-			err_msg("Cannot read value to input key: %s. rc: %d\n",
-					key_vec[i], rc);
-			goto err;
-		}
-		rc = bootenv_set(env, key_vec[i], tmp);
-		if (rc != 0) {
-			err_msg("Cannot set value key: %s. rc: %d\n",
-					key_vec[i], rc);
-			goto err;
-		}
-	}
-
-err:
-	if (key_vec != NULL)
-		free(key_vec);
-	return rc;
-}
-
-static int
-read_bootenv(const char* file, bootenv_t env)
-{
-	int rc = 0;
-	FILE* fp_in = NULL;
-
-	fp_in = fopen(file, "rb");
-	if (fp_in == NULL) {
-		err_msg("Cannot open file: %s\n", file);
-		return -EIO;
-	}
-
-	rc = bootenv_read(fp_in, env, BOOTENV_MAXSIZE);
-	if (rc != 0) {
-		err_msg("Cannot read bootenv from file %s. rc: %d\n",
-			file, rc);
-		goto err;
-	}
-
-err:
-	fclose(fp_in);
-	return rc;
-}
-
-/*
- * Read bootenv from ubi volume
- */
-static int
-ubi_read_bootenv(uint32_t devno, uint32_t id, bootenv_t env)
-{
-	libubi_t ulib;
-	int rc = 0;
-	char path[PATH_MAX];
-	FILE* fp_in = NULL;
-
-	ulib = libubi_open();
-	if (ulib == NULL) {
-		err_msg("Cannot allocate ubi structure\n");
-		return -1;
-	}
-
-	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
-
-	fp_in = fopen(path, "r");
-	if (fp_in == NULL) {
-		err_msg("Cannot open volume:%d number:%d\n", devno, id);
-		goto err;
-	}
-
-	rc = bootenv_read(fp_in, env, BOOTENV_MAXSIZE);
-	if (rc != 0) {
-		err_msg("Cannot read volume:%d number:%d\n", devno, id);
-		goto err;
-	}
-
-err:
-	if (fp_in)
-		fclose(fp_in);
-	libubi_close(ulib);
-	return rc;
-}
-
-static int
-write_bootenv(const char* file, bootenv_t env)
-{
-	int rc = 0;
-	FILE* fp_out;
-
-	fp_out = fopen(file, "wb");
-	if (fp_out == NULL) {
-		err_msg("Cannot open file: %s\n", file);
-		return -EIO;
-	}
-
-	rc = bootenv_write(fp_out, env);
-	if (rc != 0) {
-		err_msg("Cannot write bootenv to file %s. rc: %d\n", file, rc);
-		goto err;
-	}
-
-err:
-	fclose(fp_out);
-	return rc;
-}
-
-/*
- * Read bootenv from ubi volume
- */
-static int
-ubi_write_bootenv(uint32_t devno, uint32_t id, bootenv_t env)
-{
-	libubi_t ulib;
-	int rc = 0;
-	char path[PATH_MAX];
-	FILE* fp_out = NULL;
-	size_t nbytes;
-
-	rc = bootenv_size(env, &nbytes);
-	if (rc) {
-		err_msg("Cannot determine size of bootenv structure\n");
-		return rc;
-	}
-	ulib = libubi_open();
-	if (ulib == NULL) {
-		err_msg("Cannot allocate ubi structure\n");
-		return rc;
-	}
-
-	snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id);
-
-	fp_out = fopen(path, "r+");
-	if (fp_out == NULL) {
-		err_msg("Cannot fopen volume:%d number:%d\n", devno, id);
-		rc = -EBADF;
-		goto err;
-	}
-
-	rc = ubi_update_start(ulib, fileno(fp_out), nbytes);
-	if (rc != 0) {
-		err_msg("Cannot start update for %s\n", path);
-		goto err;
-	}
-
-	rc = bootenv_write(fp_out, env);
-	if (rc != 0) {
-		err_msg("Cannot write bootenv to volume %d number:%d\n",
-			devno, id);
-		goto err;
-	}
-err:
-	if( fp_out )
-		fclose(fp_out);
-	libubi_close(ulib);
-	return rc;
-}
-
-static int
-do_mirror(int volno)
-{
-	char errbuf[1024];
-	uint32_t ids[2];
-	int rc;
-	int src_volno_idx = 0;
-
-	ids[0] = EXAMPLE_BOOTENV_VOL_ID_1;
-	ids[1] = EXAMPLE_BOOTENV_VOL_ID_2;
-
-	if (volno == EXAMPLE_BOOTENV_VOL_ID_2)
-		src_volno_idx = 1;
-
-	rc = ubimirror(EXAMPLE_UBI_DEVICE, src_volno_idx, ids, 2, errbuf,
-		       sizeof errbuf);
-	if( rc )
-		err_msg(errbuf);
-	return rc;
-}
-
-int
-main(int argc, char **argv) {
-	int rc = 0;
-	bootenv_t env = NULL;
-	uint32_t boot_volno;
-	myargs args = {
-		.action = ACT_NORMAL,
-		.file_in  = NULL,
-		.file_out = NULL,
-		.side = -1,
-		.x86 = 0,
-		.both = 0,
-		.env_in = NULL,
-
-		.arg1 = NULL,
-		.options = NULL,
-	};
-
-	rc = bootenv_create(&env);
-	if (rc != 0) {
-		err_msg("Cannot create bootenv handle. rc: %d", rc);
-		goto err;
-	}
-
-	rc = bootenv_create(&(args.env_in));
-	if (rc != 0) {
-		err_msg("Cannot create bootenv handle. rc: %d", rc);
-		goto err;
-	}
-
-	parse_opt(argc, argv, &args);
-	if (args.action == ACT_ARGP_ERR) {
-		rc = -1;
-		goto err;
-	}
-	if (args.action == ACT_ARGP_ABORT) {
-		rc = 0;
-		goto out;
-	}
-
-	if ((args.side == 0) || (args.side == -1))
-		boot_volno = EXAMPLE_BOOTENV_VOL_ID_1;
-	else
-		boot_volno = EXAMPLE_BOOTENV_VOL_ID_2;
-
-	if( args.x86 )
-		rc = read_bootenv(args.file_in, env);
-	else
-		rc = ubi_read_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env);
-	if (rc != 0) {
-		goto err;
-	}
-
-	if (args.action == ACT_LIST) {
-		rc = list_bootenv(env);
-		if (rc != 0) {
-			goto err;
-		}
-		goto out;
-	}
-
-	rc = process_key_value(args.env_in, env);
-	if (rc != 0) {
-		goto err;
-	}
-
-	if( args.x86 )
-		rc = write_bootenv(args.file_in, env);
-	else
-		rc = ubi_write_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env);
-	if (rc != 0)
-		goto err;
-
-	if( args.both )		/* No side specified, update both */
-		rc = do_mirror(boot_volno);
-
- out:
- err:
-	bootenv_destroy(&env);
-	bootenv_destroy(&(args.env_in));
-	return rc;
-}
diff --git a/ubi-utils/src/peb.c b/ubi-utils/src/peb.c
deleted file mode 100644
index 08b770f..0000000
--- a/ubi-utils/src/peb.c
+++ /dev/null
@@ -1,116 +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.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "peb.h"
-
-int
-peb_cmp(peb_t eb_1, peb_t eb_2)
-{
-	assert(eb_1);
-	assert(eb_2);
-
-	return eb_1->num == eb_2->num ? 0
-		: eb_1->num > eb_2->num ? 1 : -1;
-}
-
-int
-peb_new(uint32_t eb_num, uint32_t eb_size, peb_t *peb)
-{
-	int rc = 0;
-
-	peb_t res = (peb_t) malloc(sizeof(struct peb));
-	if (!res) {
-		rc = -ENOMEM;
-		goto err;
-	}
-
-	res->num  = eb_num;
-	res->size = eb_size;
-	res->data = (uint8_t*) malloc(res->size * sizeof(uint8_t));
-	if (!res->data) {
-		rc = -ENOMEM;
-		goto err;
-	}
-	memset(res->data, 0xff, res->size);
-
-	*peb = res;
-	return 0;
-err:
-	if (res) {
-		if (res->data)
-			free(res->data);
-		free(res);
-	}
-	*peb = NULL;
-	return rc;
-}
-
-int
-peb_fill(peb_t peb, uint8_t* buf, size_t buf_size)
-{
-	if (!peb)
-		return -EINVAL;
-
-	if (buf_size > peb->size)
-		return -EINVAL;
-
-	memcpy(peb->data, buf, buf_size);
-	return 0;
-}
-
-int
-peb_write(FILE* fp_out, peb_t peb)
-{
-	size_t written = 0;
-
-	if (peb == NULL)
-		return -EINVAL;
-
-	written = fwrite(peb->data, 1, peb->size, fp_out);
-
-	if (written != peb->size)
-		return -EIO;
-
-	return 0;
-}
-
-int
-peb_free(peb_t* peb)
-{
-	peb_t tmp = *peb;
-	if (tmp) {
-		if (tmp->data)
-			free(tmp->data);
-		free(tmp);
-	}
-	*peb = NULL;
-
-	return 0;
-}
-
-void peb_dump(FILE* fp_out, peb_t peb)
-{
-	fprintf(fp_out, "num: %08d\tsize: 0x%08x\n", peb->num, peb->size);
-}
diff --git a/ubi-utils/src/peb.h b/ubi-utils/src/peb.h
deleted file mode 100644
index 246bce8..0000000
--- a/ubi-utils/src/peb.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef __RAW_BLOCK_H__
-#define __RAW_BLOCK_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: Oliver Lohmann
- */
-
-#include <stdint.h>
-#include <stdio.h>
-
-typedef struct peb *peb_t;
-struct peb {
-	uint32_t num;		/* Physical eraseblock number
-				 * in the RAW file. */
-	uint32_t size;		/* Data Size (equals physical
-				 * erase block size) */
-	uint8_t* data;		/* Data buffer */
-};
-
-int  peb_new(uint32_t peb_num, uint32_t peb_size, peb_t* peb);
-int  peb_free(peb_t* peb);
-int  peb_cmp(peb_t peb_1, peb_t peb_2);
-int  peb_write(FILE* fp_out, peb_t peb);
-void peb_dump(FILE* fp_out, peb_t peb);
-
-#endif /* __RAW_BLOCK_H__ */
diff --git a/ubi-utils/src/pfi.c b/ubi-utils/src/pfi.c
deleted file mode 100644
index fa835e2..0000000
--- a/ubi-utils/src/pfi.c
+++ /dev/null
@@ -1,458 +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.
- */
-
-/*
- * @file pfi.c
- *
- * @author Oliver Lohmann
- *	   Andreas Arnez
- *	   Joern Engel
- *	   Frank Haverkamp
- *
- * @brief libpfi holds all code to create and process pfi files.
- *
- * <oliloh@de.ibm.com> Wed Feb	8 11:38:22 CET 2006: Initial creation.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <syslog.h>
-#include <stdarg.h>
-#include <errno.h>
-
-#include "pfi.h"
-
-#define PFI_MAGIC     "PFI!\n"
-#define PFI_DATA      "DATA\n" /* The same size as PFI_MAGIC */
-#define PFI_MAGIC_LEN 5
-
-static const char copyright [] __attribute__((unused)) =
-	"Copyright (c) International Business Machines Corp., 2006";
-
-enum key_id {
-	/* version 1 */
-	key_version,	      /* must be index position 0! */
-	key_mode,
-	key_size,
-	key_crc,
-	key_label,
-	key_flags,
-	key_ubi_ids,
-	key_ubi_size,
-	key_ubi_type,
-	key_ubi_names,
-	key_ubi_alignment,
-	key_raw_starts,
-	key_raw_total_size,
-	num_keys,
-};
-
-struct pfi_header {
-	char defined[num_keys];	 /* reserve all possible keys even if
-				    version does not require this. */
-	int mode_no;		 /* current mode no. -> can only increase */
-	union {
-		char *str;
-		uint32_t num;
-	} value[num_keys];
-};
-
-
-#define PFI_MANDATORY	    0x0001
-#define PFI_STRING	    0x0002
-#define PFI_LISTVALUE	    0x0004	/* comma seperated list of nums */
-#define PFI_MANDATORY_UBI   0x0008
-#define PFI_MANDATORY_RAW   0x0010
-
-struct key_descriptor {
-	enum key_id id;
-	const char *name;
-	uint32_t flags;
-};
-
-static const struct key_descriptor key_desc_v1[] = {
-	{ key_version, "version", PFI_MANDATORY },
-	{ key_mode, "mode", PFI_MANDATORY | PFI_STRING },
-	{ key_size, "size", PFI_MANDATORY },
-	{ key_crc, "crc", PFI_MANDATORY },
-	{ key_label, "label", PFI_MANDATORY | PFI_STRING },
-	{ key_flags, "flags", PFI_MANDATORY },
-	{ key_ubi_ids, "ubi_ids", PFI_MANDATORY_UBI | PFI_STRING },
-	{ key_ubi_size, "ubi_size", PFI_MANDATORY_UBI },
-	{ key_ubi_type, "ubi_type", PFI_MANDATORY_UBI | PFI_STRING },
-	{ key_ubi_names, "ubi_names", PFI_MANDATORY_UBI | PFI_STRING },
-	{ key_ubi_alignment, "ubi_alignment", PFI_MANDATORY_UBI },
-	{ key_raw_starts, "raw_starts", PFI_MANDATORY_RAW | PFI_STRING },
-	{ key_raw_total_size, "raw_total_size", PFI_MANDATORY_RAW },
-};
-
-static const struct key_descriptor *key_descriptors[] = {
-	NULL,
-	key_desc_v1,					   /* version 1 */
-};
-
-static const int key_descriptors_max[] = {
-	0,						   /* version 0 */
-	sizeof(key_desc_v1)/sizeof(struct key_descriptor), /* version 1 */
-};
-
-#define ARRAY_SIZE(a)    (sizeof(a) / sizeof((a)[0]))
-
-static const char* modes[] = {"raw", "ubi"}; /* order isn't arbitrary! */
-
-/* latest version contains all possible keys */
-static const struct key_descriptor *key_desc = key_desc_v1;
-
-#define PFI_IS_UBI(mode) \
-	(((mode) != NULL) && (strcmp("ubi", (mode)) == 0))
-
-#define PFI_IS_RAW(mode) \
-	(((mode) != NULL) && (strcmp("raw", (mode)) == 0))
-
-/**
- * @return	 <0	On Error.
- *		>=0	Mode no.
- */
-static int
-get_mode_no(const char* mode)
-{
-	int i;
-
-	for (i = 0; i < (int)ARRAY_SIZE(modes); i++)
-		if (strcmp(mode, modes[i]) == 0)
-			return i;
-	return -1;
-}
-
-static int
-find_key_by_name (const char *name)
-{
-	int i;
-
-	for (i = 0; i < num_keys; i++) {
-		if (strcmp(name, key_desc[i].name) == 0)
-			return i;
-	}
-	return -1;
-}
-
-static int
-check_valid (pfi_header head)
-{
-	int i;
-	int max_keys;
-	uint32_t version;
-	const char *mode;
-	const struct key_descriptor *desc;
-	uint32_t to_check = PFI_MANDATORY;
-
-	/*
-	 * For the validity check the list of possible keys depends on
-	 * the version of the PFI file used.
-	 */
-	version = head->value[key_version].num;
-	if (version > PFI_HDRVERSION)
-		return PFI_ENOHEADER;
-
-	max_keys = key_descriptors_max[version];
-	desc = key_descriptors[version];
-
-	if (!desc)
-		return PFI_ENOVERSION;
-
-	mode = head->value[key_mode].str;
-	if (PFI_IS_UBI(mode)) {
-		to_check |= PFI_MANDATORY_UBI;
-	}
-	else if (PFI_IS_RAW(mode)) {
-		to_check |= PFI_MANDATORY_RAW;
-	}
-	else { /* neither UBI nor RAW == ERR */
-		return PFI_EINSUFF;
-	}
-
-	for (i = 0; i < max_keys; i++) {
-		if ((desc[i].flags & to_check) && !head->defined[i]) {
-			fprintf(stderr, "libpfi: %s missing\n", desc[i].name);
-			return PFI_EINSUFF;
-		}
-	}
-
-	return 0;
-}
-
-int pfi_header_init (pfi_header *head)
-{
-	int i;
-	pfi_header self = (pfi_header) malloc(sizeof(*self));
-
-	*head = self;
-	if (self == NULL)
-		return PFI_ENOMEM;
-
-	/* initialize maximum number of possible keys */
-	for (i = 0; i < num_keys; i++) {
-		memset(self, 0, sizeof(*self));
-		self->defined[i] = 0;
-	}
-
-	return 0;
-}
-
-int pfi_header_destroy (pfi_header *head)
-{
-	int i;
-	pfi_header self = *head;
-
-	for (i = 0; i < num_keys; i++) {
-		if (self->defined[i] && (key_desc[i].flags & PFI_STRING) &&
-		    self->value[i].str) {
-			free(self->value[i].str);
-		}
-	}
-	free(*head);
-	*head = NULL;
-	return 0;
-}
-
-int pfi_header_setnumber (pfi_header head,
-			   const char *key, uint32_t value)
-{
-	int key_id = find_key_by_name(key);
-
-	if (key_id < 0)
-		return PFI_EUNDEF;
-
-	if (key_desc[key_id].flags & PFI_STRING)
-		return PFI_EBADTYPE;
-
-	head->value[key_id].num = value;
-	head->defined[key_id] = 1;
-	return 0;
-}
-
-int pfi_header_setvalue (pfi_header head,
-			  const char *key, const char *value)
-{
-	int key_id = find_key_by_name(key);
-
-	if (value == NULL)
-		return PFI_EINSUFF;
-
-	if ((key_id < 0) || (key_id >= num_keys))
-		return PFI_EUNDEF;
-
-	if (key_desc[key_id].flags & PFI_STRING) {
-		/*
-		 * The value is a string. Copy to a newly allocated
-		 * buffer. Delete the old value, if already set.
-		 */
-		size_t len = strlen(value) + 1;
-		char *old_str = NULL;
-		char *str;
-
-		old_str = head->value[key_id].str;
-		if (old_str != NULL)
-			free(old_str);
-
-		str = head->value[key_id].str = (char *) malloc(len);
-		if (str == NULL)
-			return PFI_ENOMEM;
-
-		strcpy(str, value);
-	} else {
-		int len;
-		int ret;
-		/* FIXME: here we assume that the value is always
-		   given in hex and starts with '0x'. */
-		ret = sscanf(value, "0x%x%n", &head->value[key_id].num, &len);
-		if (ret < 1 || value[len] != '\0')
-			return PFI_EBADTYPE;
-	}
-	head->defined[key_id] = 1;
-	return 0;
-}
-
-int pfi_header_getnumber (pfi_header head,
-			   const char *key, uint32_t *value)
-{
-	int key_id = find_key_by_name(key);
-
-	if (key_id < 0)
-		return PFI_EUNDEF;
-
-	if (key_desc[key_id].flags & PFI_STRING)
-		return PFI_EBADTYPE;
-
-	if (!head->defined[key_id])
-		return PFI_EUNDEF;
-
-	*value = head->value[key_id].num;
-	return 0;
-}
-
-int pfi_header_getstring (pfi_header head,
-			   const char *key, char *value, size_t size)
-{
-	int key_id = find_key_by_name(key);
-
-	if (key_id < 0)
-		return PFI_EUNDEF;
-
-	if (!(key_desc[key_id].flags & PFI_STRING))
-		return PFI_EBADTYPE;
-
-	if (!head->defined[key_id])
-		return PFI_EUNDEF;
-
-	strncpy(value, head->value[key_id].str, size-1);
-	value[size-1] = '\0';
-	return 0;
-}
-
-int pfi_header_write (FILE *out, pfi_header head)
-{
-	int i;
-	int ret;
-
-	pfi_header_setnumber(head, "version", PFI_HDRVERSION);
-
-	if ((ret = check_valid(head)) != 0)
-		return ret;
-
-	/* OK.	Now write the header. */
-
-	ret = fwrite(PFI_MAGIC, 1, PFI_MAGIC_LEN, out);
-	if (ret < PFI_MAGIC_LEN)
-		return ret;
-
-
-	for (i = 0; i < num_keys; i++) {
-		if (!head->defined[i])
-			continue;
-
-		ret = fprintf(out, "%s=", key_desc[i].name);
-		if (ret < 0)
-			return PFI_EFILE;
-
-		if (key_desc[i].flags & PFI_STRING) {
-			ret = fprintf(out, "%s", head->value[i].str);
-			if (ret < 0)
-				return PFI_EFILE;
-		} else {
-			ret = fprintf(out, "0x%8x", head->value[i].num);
-			if (ret < 0)
-				return PFI_EFILE;
-
-		}
-		ret = fprintf(out, "\n");
-		if (ret < 0)
-			return PFI_EFILE;
-	}
-	ret = fprintf(out, "\n");
-	if (ret < 0)
-		return PFI_EFILE;
-
-	ret = fflush(out);
-	if (ret != 0)
-		return PFI_EFILE;
-
-	return 0;
-}
-
-int pfi_header_read (FILE *in, pfi_header head)
-{
-	char magic[PFI_MAGIC_LEN];
-	char mode[PFI_KEYWORD_LEN];
-	char buf[256];
-
-	if (PFI_MAGIC_LEN != fread(magic, 1, PFI_MAGIC_LEN, in))
-		return PFI_EFILE;
-	if (memcmp(magic, PFI_MAGIC, PFI_MAGIC_LEN) != 0)  {
-		if (memcmp(magic, PFI_DATA, PFI_MAGIC_LEN) == 0) {
-			return PFI_DATA_START;
-		}
-		return PFI_ENOHEADER;
-	}
-
-	while (fgets(buf, sizeof(buf), in) != NULL && buf[0] != '\n') {
-		char *value;
-		char *end;
-		value = strchr(buf, '=');
-		if (value == NULL)
-			return PFI_ENOHEADER;
-
-		*value = '\0';
-		value++;
-		end = strchr(value, '\n');
-		if (end)
-		       *end = '\0';
-
-		if (pfi_header_setvalue(head, buf, value))
-			return PFI_ENOHEADER;
-	}
-
-	if (check_valid(head) != 0)
-		return PFI_ENOHEADER;
-
-	/* set current mode no. in head */
-	pfi_header_getstring(head, "mode", mode, PFI_KEYWORD_LEN);
-	if (head->mode_no > get_mode_no(mode)) {
-		return PFI_EMODE;
-	}
-	head->mode_no = get_mode_no(mode);
-	return 0;
-}
-
-int pfi_header_dump (FILE *out, pfi_header head __attribute__((__unused__)))
-{
-	fprintf(out, "Sorry not implemented yet. Write mail to "
-		"Andreas Arnez and complain!\n");
-	return 0;
-}
-
-int pfi_read (FILE *in, pfi_read_func func, void *priv_data)
-{
-	int rc;
-	pfi_header header;
-
-	rc = pfi_header_init (&header);
-	if (0 != rc)
-		return rc;
-	if (!func)
-		return PFI_EINVAL;
-
-	while ((0 == rc) && !feof(in)) {
-		/*
-		 * Read header and check consistency of the fields.
-		 */
-		rc = pfi_header_read( in, header );
-		if (0 != rc)
-			break;
-		if (func) {
-			rc = func(in, header, priv_data);
-			if (rc != 0)
-				break;
-		}
-	}
-
-	pfi_header_destroy(&header);
-	return rc;
-}
diff --git a/ubi-utils/src/pfi.h b/ubi-utils/src/pfi.h
deleted file mode 100644
index 8c5cc07..0000000
--- a/ubi-utils/src/pfi.h
+++ /dev/null
@@ -1,244 +0,0 @@
-#ifndef __pfi_h
-#define __pfi_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.
- */
-
-/**
- * @file pfi.h
- *
- * @author Oliver Lohmann <oliloh@de.ibm.com>
- *         Andreas Arnez <arnez@de.ibm.com>
- *         Joern Engel <engeljoe@de.ibm.com>
- *         Frank Haverkamp <haverkam@de.ibm.com>
- *
- * @brief libpfi will hold all code to create and process pfi
- * images. Definitions made in this file are equaly usable for the
- * development host and the target system.
- *
- * @note This header additionally holds the official definitions for
- * the pfi headers.
- */
-
-#include <stdio.h>		/* FILE */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Definitions. */
-
-#define PFI_HDRVERSION 1	/* current header version */
-
-#define PFI_ENOVERSION 1	/* unknown version */
-#define PFI_ENOHEADER  2	/* not a pfi header */
-#define PFI_EINSUFF    3	/* insufficient information */
-#define PFI_EUNDEF     4	/* key not defined */
-#define PFI_ENOMEM     5	/* out of memory */
-#define PFI_EBADTYPE   6	/* bad data type */
-#define PFI_EFILE      7	/* file I/O error: see errno */
-#define PFI_EFILEINVAL 8	/* file format not valid */
-#define PFI_EINVAL     9	/* invalid parameter */
-#define PFI_ERANGE     10	/* invalid range */
-#define PFI_EMODE      11	/* expecting other mode in this header */
-#define PFI_DATA_START 12	/* data section starts */
-#define PFI_EMAX       13	/* should be always larger as the largest
-				   error code */
-
-#define PFI_LABEL_LEN  64	/* This is the maximum length for a
-				   PFI header label */
-#define PFI_KEYWORD_LEN 32	/* This is the maximum length for an
-				   entry in the mode and type fields */
-
-#define PFI_UBI_MAX_VOLUMES 128
-#define PFI_UBI_VOL_NAME_LEN 127
-
-/**
- * @brief The pfi header allows to set flags which influence the flashing
- * behaviour.
- */
-#define PFI_FLAG_PROTECTED   0x00000001
-
-
-/**
- * @brief Handle to pfi header. Used in most of the functions associated
- * with pfi file handling.
- */
-typedef struct pfi_header *pfi_header;
-
-
-/**
- * @brief Initialize a pfi header object.
- *
- * @param head	 Pointer to handle. This function allocates memory
- *		 for this data structure.
- * @return	 0 on success, otherwise:
- *		 PFI_ENOMEM : no memory available for the handle.
- */
-int pfi_header_init (pfi_header *head);
-
-
-/**
- * @brief Destroy a pfi header object.
- *
- * @param head	 handle. head is invalid after calling this function.
- * @return	 0 always.
- */
-int pfi_header_destroy (pfi_header *head);
-
-
-/**
- * @brief Add a key/value pair to a pfi header object.
- *
- * @param head	 handle.
- * @param key	 pointer to key string. Must be 0 terminated.
- * @param value	 pointer to value string. Must be 0 terminated.
- * @return	 0 on success, otherwise:
- *		 PFI_EUNDEF   : key was not found.
- *		 PFI_ENOMEM   : no memory available for the handle.
- *		 PFI_EBADTYPE : value is not an hex string. This happens
- *				 when the key stores an integer and the
- *				 new value is not convertable e.g. not in
- *				 0xXXXXXXXX format.
- */
-int pfi_header_setvalue (pfi_header head,
-			  const char *key, const char *value);
-
-
-/**
- * @brief Add a key/value pair to a pfi header object. Provide the
- * value as a number.
- *
- * @param head	 handle.
- * @param key	 pointer to key string. Must be 0 terminated.
- * @param value	 value to set.
- * @return	 0 on success, otherwise:
- *		 PFI_EUNDEF   : key was not found.
- *		 PFI_EBADTYPE : value is not a string. This happens
- *				 when the key stores a string.
- */
-int pfi_header_setnumber (pfi_header head,
-			   const char *key, uint32_t value);
-
-
-/**
- * @brief For a given key, return the numerical value stored in a
- * pfi header object.
- *
- * @param head	 handle.
- * @param key	 pointer to key string. Must be 0 terminated.
- * @param value	 pointer to value.
- * @return	 0 on success, otherwise:
- *		 PFI_EUNDEF   : key was not found.
- *		 PFI_EBADTYPE : stored value is not an integer but a string.
- */
-int pfi_header_getnumber (pfi_header head,
-			   const char *key, uint32_t *value);
-
-
-static inline uint32_t
-pfi_getnumber(pfi_header head, const char *key)
-{
-	uint32_t value;
-	pfi_header_getnumber(head, key, &value);
-	return value;
-}
-
-/**
- * @brief For a given key, return the string value stored in a pfi
- * header object.
- *
- * @param head	 handle.
- * @param key	 pointer to key string. Must be 0 terminated.
- * @param value	 pointer to value string. Memory must be allocated by the user.
- * @return	 0 on success, otherwise:
- *		 PFI_EUNDEF   : key was not found.
- *		 PFI_EBADTYPE : stored value is not a string but an integer.
- */
-int pfi_header_getstring (pfi_header head,
-			   const char *key, char *value, size_t size);
-
-
-/**
- * @brief Write a pfi header object into a given file.
- *
- * @param out	 output stream.
- * @param head	 handle.
- * @return	 0 on success, error values otherwise:
- *		 PFI_EINSUFF   : not all mandatory fields are filled.
- *		 PFI_ENOHEADER : wrong header version or magic number.
- *		 -E*		: see <asm/errno.h>.
- */
-int pfi_header_write (FILE *out, pfi_header head);
-
-
-/**
- * @brief Read a pfi header object from a given file.
- *
- * @param in	 input stream.
- * @param head	 handle.
- * @return	 0 on success, error values otherwise:
- *		 PFI_ENOVERSION: unknown header version.
- *		 PFI_EFILE     : cannot read enough data.
- *		 PFI_ENOHEADER : wrong header version or magic number.
- *		 -E*		: see <asm/errno.h>.
- *
- * If the header verification returned success the user can assume that
- * all mandatory fields for a particular version are accessible. Checking
- * the return code when calling the get-function for those keys is not
- * required in those cases. For optional fields the checking must still be
- * done.
- */
-int pfi_header_read (FILE *in, pfi_header head);
-
-
-/**
- * @brief Display a pfi header in human-readable form.
- *
- * @param out	 output stream.
- * @param head	 handle.
- * @return	 always 0.
- *
- * @note Prints out that it is not implemented and whom you should
- * contact if you need it urgently!.
- */
-int pfi_header_dump (FILE *out, pfi_header head);
-
-
-/*
- * @brief	 Iterates over a stream of pfi files. The iterator function
- *		 must advance the file pointer in FILE *in to the next pfi
- *		 header. Function exists on feof(in).
- *
- * @param in	 input file descriptor, must be open and valid.
- * @param func	 iterator function called when pfi header could be
- *		 read and was validated. The function must return 0 on
- *		 success.
- * @return	 See pfi_header_init and pfi_header_read.
- *		 PFI_EINVAL	  : func is not valid
- *		 0 ok.
- */
-typedef int (* pfi_read_func)(FILE *in, pfi_header hdr, void *priv_data);
-
-int pfi_read (FILE *in, pfi_read_func func, void *priv_data);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __pfi_h */
diff --git a/ubi-utils/src/pfi2bin.c b/ubi-utils/src/pfi2bin.c
deleted file mode 100644
index 34ecc92..0000000
--- a/ubi-utils/src/pfi2bin.c
+++ /dev/null
@@ -1,682 +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
- *
- * Convert a PFI file (partial flash image) into a plain binary file.
- * This tool can be used to prepare the data to be burned into flash
- * chips in a manufacturing step where the flashes are written before
- * being soldered onto the hardware. For NAND images another step is
- * required to add the right OOB data to the binary image.
- *
- * 1.3 Removed argp because we want to use uClibc.
- * 1.4 Minor cleanups
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <ubigen.h>
-#include <mtd/ubi-media.h>
-#include <mtd_swab.h>
-
-#include "config.h"
-#include "list.h"
-#include "error.h"
-#include "reader.h"
-#include "peb.h"
-#include "crc32.h"
-
-#define PROGRAM_VERSION "1.4"
-
-#define MAX_FNAME 255
-#define DEFAULT_ERASE_COUNT  0 /* Hmmm.... Perhaps */
-#define ERR_BUF_SIZE 1024
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-static uint32_t crc32_table[256];
-static char err_buf[ERR_BUF_SIZE];
-
-/*
- * Data used to buffer raw blocks which have to be
- * located at a specific point inside the generated RAW file
- */
-
-typedef enum action_t {
-	ACT_NOTHING   = 0x00000000,
-	ACT_RAW	   = 0x00000001,
-} action_t;
-
-static const char copyright [] __attribute__((unused)) =
-	"(c) Copyright IBM Corp 2006\n";
-
-static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
-	"pfi2bin - a tool to convert PFI files into binary images.\n";
-
-static const char *optionsstr =
-" Common settings:\n"
-"  -c, --copyright\n"
-"  -v, --verbose              Print more information.\n"
-"\n"
-" Input:\n"
-"  -j, --platform=pdd-file    PDD information which contains the card settings.\n"
-"\n"
-" Output:\n"
-"  -o, --output=filename      Outputfile, default: stdout.\n"
-"\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: pfi2bin [-cv?V] [-j pdd-file] [-o filename] [--copyright]\n"
-"            [--verbose] [--platform=pdd-file] [--output=filename] [--help]\n"
-"            [--usage] [--version] pfifile\n";
-
-struct option long_options[] = {
-	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
-	{ .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
-	{ .name = "platform", .has_arg = 1, .flag = NULL, .val = 'j' },
-	{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
-	{ .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}
-};
-
-typedef struct io {
-	FILE* fp_pdd;	/* a FilePointer to the PDD data */
-	FILE* fp_pfi;	/* a FilePointer to the PFI input stream */
-	FILE* fp_out;	/* a FilePointer to the output stream */
-} *io_t;
-
-typedef struct myargs {
-	/* common settings */
-	action_t action;
-	int verbose;
-	const char *f_in_pfi;
-	const char *f_in_pdd;
-	const char *f_out;
-
-	/* special stuff needed to get additional arguments */
-	char *arg1;
-	char **options;			/* [STRING...] */
-} myargs;
-
-static int
-parse_opt(int argc, char **argv, myargs *args)
-{
-	while (1) {
-		int key;
-
-		key = getopt_long(argc, argv, "cvj:o:?V", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-			/* common settings */
-			case 'v': /* --verbose=<level> */
-				args->verbose = 1;
-				break;
-
-			case 'c': /* --copyright */
-				fprintf(stderr, "%s\n", copyright);
-				exit(0);
-				break;
-
-			case 'j': /* --platform */
-				args->f_in_pdd = optarg;
-				break;
-
-			case 'o': /* --output */
-				args->f_out = optarg;
-				break;
-
-			case '?': /* help */
-				printf("pfi2bin [OPTION...] pfifile\n");
-				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);
-		}
-	}
-
-	if (optind < argc)
-		args->f_in_pfi = argv[optind++];
-
-	return 0;
-}
-
-
-static size_t
-byte_to_blk(size_t byte, size_t blk_size)
-{
-	return	(byte % blk_size) == 0
-		? byte / blk_size
-		: byte / blk_size + 1;
-}
-
-
-
-
-/**
- * @precondition  IO: File stream points to first byte of RAW data.
- * @postcondition IO: File stream points to first byte of next
- *		      or EOF.
- */
-static int
-memorize_raw_eb(pfi_raw_t pfi_raw, pdd_data_t pdd, list_t *raw_pebs,
-		io_t io)
-{
-	int rc = 0;
-	uint32_t i;
-
-	size_t read, to_read, eb_num;
-	size_t bytes_left;
-	list_t pebs = *raw_pebs;
-	peb_t	peb  = NULL;
-
-	long old_file_pos = ftell(io->fp_pfi);
-	for (i = 0; i < pfi_raw->starts_size; i++) {
-		bytes_left = pfi_raw->data_size;
-		rc = fseek(io->fp_pfi, old_file_pos, SEEK_SET);
-		if (rc != 0)
-			goto err;
-
-		eb_num = byte_to_blk(pfi_raw->starts[i], pdd->eb_size);
-		while (bytes_left) {
-			to_read = MIN(bytes_left, pdd->eb_size);
-			rc = peb_new(eb_num++, pdd->eb_size, &peb);
-			if (rc != 0)
-				goto err;
-			read = fread(peb->data, 1, to_read, io->fp_pfi);
-			if (read != to_read) {
-				rc = -EIO;
-				goto err;
-			}
-			pebs = append_elem(peb, pebs);
-			bytes_left -= read;
-		}
-
-	}
-	*raw_pebs = pebs;
-	return 0;
-err:
-	pebs = remove_all((free_func_t)&peb_free, pebs);
-	return rc;
-}
-
-static int
-convert_ubi_volume(pfi_ubi_t ubi, pdd_data_t pdd, list_t raw_pebs,
-		struct ubi_vtbl_record *vol_tab,
-		size_t *ebs_written, io_t io)
-{
-	int rc = 0;
-	uint32_t i, j;
-	peb_t raw_peb;
-	peb_t cmp_peb;
-	ubi_info_t u;
-	size_t leb_total = 0;
-	uint8_t vol_type;
-
-	switch (ubi->type) {
-	case pfi_ubi_static:
-		vol_type = UBI_VID_STATIC; break;
-	case pfi_ubi_dynamic:
-		vol_type = UBI_VID_DYNAMIC; break;
-	default:
-		vol_type = UBI_VID_DYNAMIC;
-	}
-
-	rc = peb_new(0, 0, &cmp_peb);
-	if (rc != 0)
-		goto err;
-
-	long old_file_pos = ftell(io->fp_pfi);
-	for (i = 0; i < ubi->ids_size; i++) {
-		rc = fseek(io->fp_pfi, old_file_pos, SEEK_SET);
-		if (rc != 0)
-			goto err;
-		rc = ubigen_create(&u, ubi->ids[i], vol_type,
-				   pdd->eb_size, DEFAULT_ERASE_COUNT,
-				   ubi->alignment, UBI_VERSION,
-				   pdd->vid_hdr_offset, 0, ubi->data_size,
-				   io->fp_pfi, io->fp_out);
-		if (rc != 0)
-			goto err;
-
-		rc = ubigen_get_leb_total(u, &leb_total);
-		if (rc != 0)
-			goto err;
-
-		j = 0;
-		while(j < leb_total) {
-			cmp_peb->num = *ebs_written;
-			raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb,
-					raw_pebs);
-			if (raw_peb) {
-				rc = peb_write(io->fp_out, raw_peb);
-			}
-			else {
-				rc = ubigen_write_leb(u, NO_ERROR);
-				j++;
-			}
-			if (rc != 0)
-				goto err;
-			(*ebs_written)++;
-		}
-		/* memorize volume table entry */
-		rc = ubigen_set_lvol_rec(u, ubi->size,
-				ubi->names[i],
-				(void*) &vol_tab[ubi->ids[i]]);
-		if (rc != 0)
-			goto err;
-		ubigen_destroy(&u);
-	}
-
-	peb_free(&cmp_peb);
-	return 0;
-
-err:
-	peb_free(&cmp_peb);
-	ubigen_destroy(&u);
-	return rc;
-}
-
-
-static FILE*
-my_fmemopen (void *buf, size_t size, const char *opentype)
-{
-    FILE* f;
-    size_t ret;
-
-    assert(strcmp(opentype, "r") == 0);
-
-    f = tmpfile();
-    ret = fwrite(buf, 1, size, f);
-    rewind(f);
-
-    return f;
-}
-
-/**
- * @brief		Builds a UBI volume table from a volume entry list.
- * @return 0		On success.
- *	   else		Error.
- */
-static int
-write_ubi_volume_table(pdd_data_t pdd, list_t raw_pebs,
-		struct ubi_vtbl_record *vol_tab, size_t vol_tab_size,
-		size_t *ebs_written, io_t io)
-{
-	int rc = 0;
-	ubi_info_t u;
-	peb_t raw_peb;
-	peb_t cmp_peb;
-	size_t leb_size, leb_total, j = 0;
-	uint8_t *ptr = NULL;
-	FILE* fp_leb = NULL;
-	int vt_slots;
-	size_t vol_tab_size_limit;
-
-	rc = peb_new(0, 0, &cmp_peb);
-	if (rc != 0)
-		goto err;
-
-	/* @FIXME: Artem creates one volume with 2 LEBs.
-	 * IMO 2 volumes would be more convenient. In order
-	 * to get 2 reserved LEBs from ubigen, I have to
-	 * introduce this stupid mechanism. Until no final
-	 * decision of the VTAB structure is made... Good enough.
-	 */
-	rc = ubigen_create(&u, UBI_LAYOUT_VOLUME_ID, UBI_VID_DYNAMIC,
-			   pdd->eb_size, DEFAULT_ERASE_COUNT,
-			   1, UBI_VERSION,
-			   pdd->vid_hdr_offset, UBI_COMPAT_REJECT,
-			   vol_tab_size, stdin, io->fp_out);
-			   /* @FIXME stdin for fp_in is a hack */
-	if (rc != 0)
-		goto err;
-	rc = ubigen_get_leb_size(u, &leb_size);
-	if (rc != 0)
-		goto err;
-	ubigen_destroy(&u);
-
-	/*
-	 * The number of supported volumes is restricted by the eraseblock size
-	 * and by the UBI_MAX_VOLUMES constant.
-	 */
-	vt_slots = leb_size / UBI_VTBL_RECORD_SIZE;
-	if (vt_slots > UBI_MAX_VOLUMES)
-		vt_slots = UBI_MAX_VOLUMES;
-	vol_tab_size_limit = vt_slots * UBI_VTBL_RECORD_SIZE;
-
-	ptr = (uint8_t*) malloc(leb_size * sizeof(uint8_t));
-	if (ptr == NULL)
-		goto err;
-
-	memset(ptr, 0xff, leb_size);
-	memcpy(ptr, vol_tab, vol_tab_size_limit);
-	fp_leb = my_fmemopen(ptr, leb_size, "r");
-
-	rc = ubigen_create(&u, UBI_LAYOUT_VOLUME_ID, UBI_VID_DYNAMIC,
-			   pdd->eb_size, DEFAULT_ERASE_COUNT,
-			   1, UBI_VERSION, pdd->vid_hdr_offset,
-			   UBI_COMPAT_REJECT, leb_size * UBI_LAYOUT_VOLUME_EBS,
-			   fp_leb, io->fp_out);
-	if (rc != 0)
-		goto err;
-	rc = ubigen_get_leb_total(u, &leb_total);
-	if (rc != 0)
-		goto err;
-
-	long old_file_pos = ftell(fp_leb);
-	while(j < leb_total) {
-		rc = fseek(fp_leb, old_file_pos, SEEK_SET);
-		if (rc != 0)
-			goto err;
-
-		cmp_peb->num = *ebs_written;
-		raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb,
-				raw_pebs);
-		if (raw_peb) {
-			rc = peb_write(io->fp_out, raw_peb);
-		}
-		else {
-			rc = ubigen_write_leb(u, NO_ERROR);
-			j++;
-		}
-
-		if (rc != 0)
-			goto err;
-		(*ebs_written)++;
-	}
-
-err:
-	free(ptr);
-	peb_free(&cmp_peb);
-	ubigen_destroy(&u);
-	fclose(fp_leb);
-	return rc;
-}
-
-static int
-write_remaining_raw_ebs(pdd_data_t pdd, list_t raw_blocks, size_t *ebs_written,
-			FILE* fp_out)
-{
-	int rc = 0;
-	uint32_t j, delta;
-	list_t ptr;
-	peb_t empty_eb, peb;
-
-	/* create an empty 0xff EB (for padding) */
-	rc = peb_new(0, pdd->eb_size, &empty_eb);
-
-	foreach(peb, ptr, raw_blocks) {
-		if (peb->num < *ebs_written) {
-			continue; /* omit blocks which
-				     are already passed */
-		}
-
-		if (peb->num < *ebs_written) {
-			err_msg("eb_num: %d\n", peb->num);
-			err_msg("Bug: This should never happen. %d %s",
-				__LINE__, __FILE__);
-			goto err;
-		}
-
-		delta = peb->num - *ebs_written;
-		if (((delta + *ebs_written) * pdd->eb_size) > pdd->flash_size) {
-			err_msg("RAW block outside of flash_size.");
-			goto err;
-		}
-		for (j = 0; j < delta; j++) {
-			rc = peb_write(fp_out, empty_eb);
-			if (rc != 0)
-				goto err;
-			(*ebs_written)++;
-		}
-		rc = peb_write(fp_out, peb);
-		if (rc != 0)
-			goto err;
-		(*ebs_written)++;
-	}
-
-err:
-	peb_free(&empty_eb);
-	return rc;
-}
-
-static int
-init_vol_tab(struct ubi_vtbl_record **vol_tab, size_t *vol_tab_size)
-{
-	uint32_t crc;
-	size_t i;
-	struct ubi_vtbl_record* res = NULL;
-
-	*vol_tab_size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
-
-	res = (struct ubi_vtbl_record*) calloc(1, *vol_tab_size);
-	if (vol_tab == NULL) {
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < UBI_MAX_VOLUMES; i++) {
-		crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
-			&(res[i]), UBI_VTBL_RECORD_SIZE_CRC);
-		res[i].crc = cpu_to_be32(crc);
-	}
-
-	*vol_tab = res;
-	return 0;
-}
-
-static int
-create_raw(io_t io)
-{
-	int rc = 0;
-	size_t ebs_written = 0; /* eraseblocks written already... */
-	size_t vol_tab_size;
-	list_t ptr;
-
-	list_t pfi_raws = mk_empty(); /* list of raw sections from a pfi */
-	list_t pfi_ubis = mk_empty(); /* list of ubi sections from a pfi */
-	list_t raw_pebs	 = mk_empty(); /* list of raw eraseblocks */
-
-	struct ubi_vtbl_record *vol_tab = NULL;
-	pdd_data_t pdd = NULL;
-
-	rc = init_vol_tab (&vol_tab, &vol_tab_size);
-	if (rc != 0) {
-		err_msg("Cannot initialize volume table.");
-		goto err;
-	}
-
-	rc = read_pdd_data(io->fp_pdd, &pdd,
-			err_buf, ERR_BUF_SIZE);
-	if (rc != 0) {
-		err_msg("Cannot read necessary pdd_data: %s rc: %d",
-				err_buf, rc);
-		goto err;
-	}
-
-	rc = read_pfi_headers(&pfi_raws, &pfi_ubis, io->fp_pfi,
-			err_buf, ERR_BUF_SIZE);
-	if (rc != 0) {
-		err_msg("Cannot read pfi header: %s rc: %d",
-				err_buf, rc);
-		goto err;
-	}
-
-	pfi_raw_t pfi_raw;
-	foreach(pfi_raw, ptr, pfi_raws) {
-		rc = memorize_raw_eb(pfi_raw, pdd, &raw_pebs,
-			io);
-		if (rc != 0) {
-			err_msg("Cannot create raw_block in mem. rc: %d\n",
-				rc);
-			goto err;
-		}
-	}
-
-	pfi_ubi_t pfi_ubi;
-	foreach(pfi_ubi, ptr, pfi_ubis) {
-		rc = convert_ubi_volume(pfi_ubi, pdd, raw_pebs,
-					vol_tab, &ebs_written, io);
-		if (rc != 0) {
-			err_msg("Cannot convert UBI volume. rc: %d\n", rc);
-			goto err;
-		}
-	}
-
-	rc = write_ubi_volume_table(pdd, raw_pebs, vol_tab, vol_tab_size,
-			&ebs_written, io);
-	if (rc != 0) {
-		err_msg("Cannot write UBI volume table. rc: %d\n", rc);
-		goto err;
-	}
-
-	rc  = write_remaining_raw_ebs(pdd, raw_pebs, &ebs_written, io->fp_out);
-	if (rc != 0)
-		goto err;
-
-	if (io->fp_out != stdout)
-		info_msg("Physical eraseblocks written: %8d\n", ebs_written);
-err:
-	free(vol_tab);
-	pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws);
-	pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis);
-	raw_pebs = remove_all((free_func_t)&peb_free, raw_pebs);
-	free_pdd_data(&pdd);
-	return rc;
-}
-
-
-/* ------------------------------------------------------------------------- */
-static void
-open_io_handle(myargs *args, io_t io)
-{
-	/* set PDD input */
-	io->fp_pdd = fopen(args->f_in_pdd, "r");
-	if (io->fp_pdd == NULL) {
-		err_sys("Cannot open: %s", args->f_in_pdd);
-	}
-
-	/* set PFI input */
-	io->fp_pfi = fopen(args->f_in_pfi, "r");
-	if (io->fp_pfi == NULL) {
-		err_sys("Cannot open PFI input file: %s", args->f_in_pfi);
-	}
-
-	/* set output prefix */
-	if (strcmp(args->f_out,"") == 0)
-		io->fp_out = stdout;
-	else {
-		io->fp_out = fopen(args->f_out, "wb");
-		if (io->fp_out == NULL) {
-			err_sys("Cannot open output file: %s", args->f_out);
-		}
-	}
-}
-
-static void
-close_io_handle(io_t io)
-{
-	if (fclose(io->fp_pdd) != 0) {
-		err_sys("Cannot close PDD file.");
-	}
-	if (fclose(io->fp_pfi) != 0) {
-		err_sys("Cannot close PFI file.");
-	}
-	if (io->fp_out != stdout) {
-		if (fclose(io->fp_out) != 0) {
-			err_sys("Cannot close output file.");
-		}
-	}
-
-	io->fp_pdd = NULL;
-	io->fp_pfi = NULL;
-	io->fp_out = NULL;
-}
-
-int
-main(int argc, char *argv[])
-{
-	int rc = 0;
-
-	ubigen_init();
-	init_crc32_table(crc32_table);
-
-	struct io io = {NULL, NULL, NULL};
-	myargs args = {
-		.action = ACT_RAW,
-		.verbose = 0,
-
-		.f_in_pfi = "",
-		.f_in_pdd = "",
-		.f_out = "",
-
-		/* arguments */
-		.arg1 = NULL,
-		.options = NULL,
-	};
-
-	/* parse arguments */
-	parse_opt(argc, argv, &args);
-
-	if (strcmp(args.f_in_pfi, "") == 0) {
-		err_quit("No PFI input file specified!");
-	}
-
-	if (strcmp(args.f_in_pdd, "") == 0) {
-		err_quit("No PDD input file specified!");
-	}
-
-	open_io_handle(&args, &io);
-
-	info_msg("[ Creating RAW...");
-	rc = create_raw(&io);
-	if (rc != 0) {
-		err_msg("Creating RAW failed.");
-		goto err;
-	}
-
-err:
-	close_io_handle(&io);
-	if (rc != 0) {
-		remove(args.f_out);
-	}
-
-	return rc;
-}
diff --git a/ubi-utils/src/pfiflash.c b/ubi-utils/src/pfiflash.c
deleted file mode 100644
index 754fe33..0000000
--- a/ubi-utils/src/pfiflash.c
+++ /dev/null
@@ -1,264 +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
- *         Frank Haverkamp
- *
- * Process a PFI (partial flash image) and write the data to the
- * specified UBI volumes. This tool is intended to be used for system
- * update using PFI files.
- *
- * 1.1 fixed output to stderr and stdout in logfile mode.
- * 1.2 updated.
- * 1.3 removed argp parsing to be able to use uClib.
- * 1.4 Minor cleanups.
- * 1.5 Forgot to delete raw block before updating it.
- * 1.6 Migrated to new libubi.
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <pfiflash.h>
-#undef DEBUG
-#include "error.h"
-#include "config.h"
-
-#define PROGRAM_VERSION  "1.6"
-
-static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
-	"pfiflash - a tool for updating a controller with PFI files.\n";
-
-static const char *optionsstr =
-" Standard options:\n"
-"  -c, --copyright            Print copyright information.\n"
-"  -l, --logfile=<file>       Write a logfile to <file>.\n"
-"  -v, --verbose              Be verbose during program execution.\n"
-"\n"
-" Process options:\n"
-"  -C, --complete             Execute a complete system update. Updates both\n"
-"                             sides.\n"
-"  -p, --pdd-update=<type>    Specify the pdd-update algorithm. <type> is either\n"
-"                             'keep', 'merge' or 'overwrite'.\n"
-"  -r, --raw-flash=<dev>      Flash the raw data. Use the specified mtd device.\n"
-"  -s, --side=<seqnum>        Select the side which shall be updated.\n"
-"  -x, --compare              Only compare on-flash and pfi data, print info if\n"
-"                             an update is neccessary and return appropriate\n"
-"                             error code.\n"
-"\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: pfiflash [-cvC?V] [-l <file>] [-p <type>] [-r <dev>] [-s <seqnum>]\n"
-"            [--copyright] [--logfile=<file>] [--verbose] [--complete]\n"
-"            [--pdd-update=<type>] [--raw-flash=<dev>] [--side=<seqnum>]\n"
-"            [--compare] [--help] [--usage] [--version] [pfifile]\n";
-
-static const char copyright [] __attribute__((unused)) =
-	"Copyright IBM Corp 2006";
-
-struct option long_options[] = {
-	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
-	{ .name = "logfile", .has_arg = 1, .flag = NULL, .val = 'l' },
-	{ .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
-	{ .name = "complete", .has_arg = 0, .flag = NULL, .val = 'C' },
-	{ .name = "pdd-update", .has_arg = 1, .flag = NULL, .val = 'p' },
-	{ .name = "raw-flash", .has_arg = 1, .flag = NULL, .val = 'r' },
-	{ .name = "side", .has_arg = 1, .flag = NULL, .val = 's' },
-	{ .name = "compare", .has_arg = 0, .flag = NULL, .val = 'x' },
-	{ .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}
-};
-
-typedef struct myargs {
-	int verbose;
-	const char *logfile;
-	const char *raw_dev;
-
-	pdd_handling_t pdd_handling;
-	int seqnum;
-	int compare;
-	int complete;
-
-	FILE* fp_in;
-
-	/* special stuff needed to get additional arguments */
-	char *arg1;
-	char **options;		/* [STRING...] */
-} myargs;
-
-static pdd_handling_t
-get_pdd_handling(const char* str)
-{
-	if (strcmp(str, "keep") == 0) {
-		return PDD_KEEP;
-	}
-	if (strcmp(str, "merge") == 0) {
-		return PDD_MERGE;
-	}
-	if (strcmp(str, "overwrite") == 0) {
-		return PDD_OVERWRITE;
-	}
-
-	return -1;
-}
-
-static int
-get_update_seqnum(const char* str)
-{
-	uint32_t i = strtoul(str, NULL, 0);
-
-	if ((i != 0) && (i != 1)) {
-		return -1;
-	}
-
-	return i;
-}
-
-
-static int
-parse_opt(int argc, char **argv, myargs *args)
-{
-	while (1) {
-		int key;
-
-		key = getopt_long(argc, argv, "cl:vCp:r:s:x?V",
-				  long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-			/* standard options */
-			case 'c':
-				err_msg("%s\n", copyright);
-				exit(0);
-				break;
-			case 'v':
-				args->verbose = 1;
-				break;
-			case 'l':
-				args->logfile = optarg;
-				break;
-				/* process options */
-			case 'C':
-				args->complete = 1;
-				break;
-			case 'p':
-				args->pdd_handling = get_pdd_handling(optarg);
-				if ((int)args->pdd_handling < 0) {
-					err_quit("Unknown PDD handling: %s.\n"
-						 "Please use either "
-						 "'keep', 'merge' or"
-						 "'overwrite'.\n'");
-				}
-				break;
-			case 's':
-				args->seqnum = get_update_seqnum(optarg);
-				if (args->seqnum < 0) {
-					err_quit("Unsupported side: %s.\n"
-						 "Supported sides are '0' "
-						 "and '1'\n", optarg);
-				}
-				break;
-			case 'x':
-				args->compare = 1;
-				break;
-			case 'r':
-				args->raw_dev = optarg;
-				break;
-			case '?': /* help */
-				err_msg("Usage: pfiflash [OPTION...] [pfifile]");
-				err_msg("%s", doc);
-				err_msg("%s", optionsstr);
-				err_msg("\nReport bugs to %s\n",
-					PACKAGE_BUGREPORT);
-				exit(0);
-				break;
-			case 'V':
-				err_msg("%s", PROGRAM_VERSION);
-				exit(0);
-				break;
-			default:
-				err_msg("%s", usage);
-				exit(-1);
-
-		}
-	}
-
-	if (optind < argc) {
-		args->fp_in = fopen(argv[optind++], "r");
-		if ((args->fp_in) == NULL) {
-			err_sys("Cannot open PFI file %s for input",
-				argv[optind]);
-		}
-	}
-
-	return 0;
-}
-
-int main (int argc, char** argv)
-{
-	int rc = 0;
-	char err_buf[PFIFLASH_MAX_ERR_BUF_SIZE];
-	memset(err_buf, '\0', PFIFLASH_MAX_ERR_BUF_SIZE);
-
-	myargs args = {
-		.verbose    = 0,
-		.seqnum	    = -1,
-		.compare    = 0,
-		.complete   = 0,
-		.logfile    = NULL, /* "/tmp/pfiflash.log", */
-		.pdd_handling = PDD_KEEP,
-		.fp_in	    = stdin,
-		.raw_dev    = NULL,
-	};
-
-	parse_opt(argc, argv, &args);
-	error_initlog(args.logfile);
-
-	if (!args.fp_in) {
-		rc = -1;
-		snprintf(err_buf, PFIFLASH_MAX_ERR_BUF_SIZE,
-			 "No PFI input file specified!\n");
-		goto err;
-	}
-
-	rc = pfiflash_with_options(args.fp_in, args.complete, args.seqnum,
-			args.compare, args.pdd_handling, args.raw_dev, err_buf,
-			PFIFLASH_MAX_ERR_BUF_SIZE);
-	if (rc < 0) {
-		goto err_fp;
-	}
-
- err_fp:
-	if (args.fp_in != stdin)
-		fclose(args.fp_in);
- err:
-	if (rc != 0)
-		err_msg("pfiflash: %s\nrc: %d\n", err_buf, rc);
-	return rc;
-}
diff --git a/ubi-utils/src/pfiflash.h b/ubi-utils/src/pfiflash.h
deleted file mode 100644
index 039705d..0000000
--- a/ubi-utils/src/pfiflash.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef __PFIFLASH_H__
-#define __PFIFLASH_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.
- */
-
-/**
- *
- * @file pfi.h
- *
- * @author Oliver Lohmann <oliloh@de.ibm.com>
- *
- * @brief The pfiflash library offers an interface for using the
- * pfiflash * utility.
- */
-
-#include <stdio.h>		/* FILE */
-
-#define PFIFLASH_MAX_ERR_BUF_SIZE 1024
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum pdd_handling_t
-{
-	PDD_KEEP = 0,
-	PDD_MERGE,
-	PDD_OVERWRITE,
-	PDD_HANDLING_NUM, /* always the last item */
-} pdd_handling_t; /**< Possible PDD handle algorithms. */
-
-/**
- * @brief Flashes a PFI file to UBI Device 0.
- * @param complete	[0|1] Do a complete system update.
- * @param seqnum	Index in a redundant group.
- * @param compare	[0|1] Compare contents.
- * @param pdd_handling	The PDD handling algorithm.
- * @param rawdev	Device to use for raw flashing
- * @param err_buf	An error buffer.
- * @param err_buf_size	Size of the error buffer.
- */
-int pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare,
-		pdd_handling_t pdd_handling, const char* rawdev,
-		char *err_buf, size_t err_buf_size);
-
-/**
- * @brief Flashes a PFI file to UBI Device 0.
- * @param complete	[0|1] Do a complete system update.
- * @param seqnum	Index in a redundant group.
- * @param pdd_handling	The PDD handling algorithm.
- * @param err_buf	An error buffer.
- * @param err_buf_size	Size of the error buffer.
- */
-int pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling,
-		char *err_buf, size_t err_buf_size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __PFIFLASH_H__ */
diff --git a/ubi-utils/src/pfiflash_error.h b/ubi-utils/src/pfiflash_error.h
deleted file mode 100644
index 0f27f4a..0000000
--- a/ubi-utils/src/pfiflash_error.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef __PFIFLASH_ERROR_H__
-#define __PFIFLASH_ERROR_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: Drake Dowsett <dowsett@de.ibm.com>
- * Contact: Andreas Arnez <arnez@de.ibm.com>
- */
-
-enum pfiflash_err {
-	PFIFLASH_ERR_EOF = 1,
-	PFIFLASH_ERR_FIO,
-	PFIFLASH_ERR_UBI_OPEN,
-	PFIFLASH_ERR_UBI_CLOSE,
-	PFIFLASH_ERR_UBI_MKVOL,
-	PFIFLASH_ERR_UBI_RMVOL,
-	PFIFLASH_ERR_UBI_VOL_UPDATE,
-	PFIFLASH_ERR_UBI_VOL_FOPEN,
-	PFIFLASH_ERR_UBI_UNKNOWN,
-	PFIFLASH_ERR_UBI_VID_OOB,
-	PFIFLASH_ERR_BOOTENV_CREATE,
-	PFIFLASH_ERR_BOOTENV_READ,
-	PFIFLASH_ERR_BOOTENV_SIZE,
-	PFIFLASH_ERR_BOOTENV_WRITE,
-	PFIFLASH_ERR_PDD_UNKNOWN,
-	PFIFLASH_ERR_MTD_OPEN,
-	PFIFLASH_ERR_MTD_CLOSE,
-	PFIFLASH_ERR_CRC_CHECK,
-	PFIFLASH_ERR_MTD_ERASE,
-	PFIFLASH_ERR_COMPARE,
-	PFIFLASH_CMP_DIFF
-};
-
-const char *const PFIFLASH_ERRSTR[] = {
-	"",
-	"unexpected EOF",
-	"file I/O error",
-	"couldn't open UBI",
-	"couldn't close UBI",
-	"couldn't make UBI volume %d",
-	"couldn't remove UBI volume %d",
-	"couldn't update UBI volume %d",
-	"couldn't open UBI volume %d",
-	"unknown UBI operation",
-	"PFI data contains out of bounds UBI id %d",
-	"couldn't create bootenv%s",
-	"couldn't read bootenv",
-	"couldn't resize bootenv",
-	"couldn't write bootenv on ubi%d_%d",
-	"unknown PDD handling algorithm",
-	"couldn't open MTD device %s",
-	"couldn't close MTD device %s",
-	"CRC check failed: given=0x%08x, calculated=0x%08x",
-	"couldn't erase raw mtd region",
-	"couldn't compare volumes",
-	"on-flash data differ from pfi data, update is neccessary"
-};
-
-#endif /* __PFIFLASH_ERROR_H__ */
diff --git a/ubi-utils/src/reader.c b/ubi-utils/src/reader.c
deleted file mode 100644
index 0ea8c6d..0000000
--- a/ubi-utils/src/reader.c
+++ /dev/null
@@ -1,482 +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
- *
- * Read in PFI (partial flash image) data and store it into internal
- * data structures for further processing. Take also care about
- * special handling if the data contains PDD (platform description
- * data/boot-parameters).
- */
-
-#include <string.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "bootenv.h"
-#include "reader.h"
-
-#define __unused __attribute__((unused))
-
-/* @FIXME hard coded offsets right now - get them from Artem? */
-#define NAND2048_DEFAULT_VID_HDR_OFF 1984
-#define NAND512_DEFAULT_VID_HDR_OFF  448
-#define NOR_DEFAULT_VID_HDR_OFF      64
-
-#define EBUF_PFI(fmt...)						\
-	do { int i = snprintf(err_buf, err_buf_size, "%s\n", label);	\
-	     snprintf(err_buf + i, err_buf_size - i, fmt);		\
-	} while (0)
-
-#define EBUF(fmt...) \
-	do { snprintf(err_buf, err_buf_size, fmt); } while (0)
-
-
-int
-read_pdd_data(FILE* fp_pdd, pdd_data_t* pdd_data,
-	      char* err_buf, size_t err_buf_size)
-{
-	int rc = 0;
-	bootenv_t pdd = NULL;
-	pdd_data_t res = NULL;
-	const char* value;
-
-	res = (pdd_data_t) malloc(sizeof(struct pdd_data));
-	if (!res) {
-		rc = -ENOMEM;
-		goto err;
-	}
-	rc = bootenv_create(&pdd);
-	if (rc != 0) {
-		goto err;
-	}
-	rc = bootenv_read_txt(fp_pdd, pdd);
-	if (rc != 0) {
-		goto err;
-	}
-	rc = bootenv_get(pdd, "flash_type", &value);
-	if (rc != 0) {
-		goto err;
-	}
-
-	if (strcmp(value, "NAND") == 0) {
-
-		rc = bootenv_get_num(pdd, "flash_page_size",
-			     &(res->flash_page_size));
-		if (rc != 0) {
-			EBUF("Cannot read 'flash_page_size' from pdd.");
-			goto err;
-		}
-		res->flash_type = NAND_FLASH;
-
-		switch (res->flash_page_size) {
-		case 512:
-			res->vid_hdr_offset = NAND512_DEFAULT_VID_HDR_OFF;
-			break;
-		case 2048:
-			res->vid_hdr_offset = NAND2048_DEFAULT_VID_HDR_OFF;
-			break;
-		default:
-			EBUF("Unsupported  'flash_page_size' %d.",
-			     res->flash_page_size);
-			goto err;
-		}
-	}
-	else if (strcmp(value, "NOR") == 0){
-		res->flash_type = NOR_FLASH;
-		res->vid_hdr_offset = NOR_DEFAULT_VID_HDR_OFF;
-	}
-	else {
-		snprintf(err_buf, err_buf_size,
-			 "Unkown flash type: %s", value);
-		goto err;
-	}
-
-	rc = bootenv_get_num(pdd, "flash_eraseblock_size",
-			     &(res->eb_size));
-	if (rc != 0) {
-		EBUF("Cannot read 'flash_eraseblock_size' from pdd.");
-		goto err;
-	}
-
-	rc = bootenv_get_num(pdd, "flash_size",
-			     &(res->flash_size));
-	if (rc != 0) {
-		EBUF("Cannot read 'flash_size' from pdd.");
-		goto err;
-	}
-
-	goto out;
- err:
-	if (res) {
-		free(res);
-		res = NULL;
-	}
- out:
-	bootenv_destroy(&pdd);
-	*pdd_data = res;
-	return rc;
-}
-
-int
-read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_raw_t* pfi_raw,
-	     const char* label, char* err_buf, size_t err_buf_size)
-{
-	int rc = 0;
-	char tmp_str[PFI_KEYWORD_LEN];
-	bootenv_list_t raw_start_list = NULL;
-	pfi_raw_t res;
-	size_t size;
-
-	res = (pfi_raw_t) malloc(sizeof(struct pfi_raw));
-	if (!res)
-		return -ENOMEM;
-
-	rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size));
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'size' from PFI.");
-		goto err;
-	}
-
-	rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc));
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'crc' from PFI.");
-		goto err;
-	}
-
-	rc = pfi_header_getstring(pfi_hd, "raw_starts",
-				  tmp_str, PFI_KEYWORD_LEN);
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'raw_starts' from PFI.");
-		goto err;
-	}
-
-	rc = bootenv_list_create(&raw_start_list);
-	if (rc != 0) {
-		goto err;
-	}
-
-	rc = bootenv_list_import(raw_start_list, tmp_str);
-	if (rc != 0) {
-		EBUF_PFI("Cannot translate PFI value: %s", tmp_str);
-		goto err;
-	}
-
-	rc = bootenv_list_to_num_vector(raw_start_list,
-					&size, &(res->starts));
-	res->starts_size = size;
-
-	if (rc != 0) {
-		EBUF_PFI("Cannot create numeric value array: %s", tmp_str);
-		goto err;
-	}
-
-	goto out;
-
- err:
-	if (res) {
-		free(res);
-		res = NULL;
-	}
- out:
-	bootenv_list_destroy(&raw_start_list);
-	*pfi_raw = res;
-	return rc;
-}
-
-int
-read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi,
-	     const char *label, char* err_buf, size_t err_buf_size)
-{
-	int rc = 0;
-	const char** tmp_names = NULL;
-	char tmp_str[PFI_KEYWORD_LEN];
-	bootenv_list_t ubi_id_list = NULL;
-	bootenv_list_t ubi_name_list = NULL;
-	pfi_ubi_t res;
-	uint32_t i;
-	size_t size;
-
-	res = (pfi_ubi_t) calloc(1, sizeof(struct pfi_ubi));
-	if (!res)
-		return -ENOMEM;
-
-	rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size));
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'size' from PFI.");
-		goto err;
-	}
-
-	rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc));
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'crc' from PFI.");
-		goto err;
-	}
-
-	rc = pfi_header_getstring(pfi_hd, "ubi_ids", tmp_str, PFI_KEYWORD_LEN);
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'ubi_ids' from PFI.");
-		goto err;
-	}
-
-	rc = bootenv_list_create(&ubi_id_list);
-	if (rc != 0) {
-		goto err;
-	}
-	rc = bootenv_list_create(&ubi_name_list);
-	if (rc != 0) {
-		goto err;
-	}
-
-	rc = bootenv_list_import(ubi_id_list, tmp_str);
-	if (rc != 0) {
-		EBUF_PFI("Cannot translate PFI value: %s", tmp_str);
-		goto err;
-	}
-
-	rc = bootenv_list_to_num_vector(ubi_id_list, &size,
-					&(res->ids));
-	res->ids_size = size;
-	if (rc != 0) {
-		EBUF_PFI("Cannot create numeric value array: %s", tmp_str);
-		goto err;
-	}
-
-	if (res->ids_size == 0) {
-		rc = -1;
-		EBUF_PFI("Sanity check failed: No ubi_ids specified.");
-		goto err;
-	}
-
-	rc = pfi_header_getstring(pfi_hd, "ubi_type",
-				  tmp_str, PFI_KEYWORD_LEN);
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'ubi_type' from PFI.");
-		goto err;
-	}
-	if (strcmp(tmp_str, "static") == 0)
-		res->type = pfi_ubi_static;
-	else if (strcmp(tmp_str, "dynamic") == 0)
-		res->type = pfi_ubi_dynamic;
-	else {
-		EBUF_PFI("Unknown ubi_type in PFI.");
-		goto err;
-	}
-
-	rc = pfi_header_getnumber(pfi_hd, "ubi_alignment", &(res->alignment));
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'ubi_alignment' from PFI.");
-		goto err;
-	}
-
-	rc = pfi_header_getnumber(pfi_hd, "ubi_size", &(res->size));
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'ubi_size' from PFI.");
-		goto err;
-	}
-
-	rc = pfi_header_getstring(pfi_hd, "ubi_names",
-				  tmp_str, PFI_KEYWORD_LEN);
-	if (rc != 0) {
-		EBUF_PFI("Cannot read 'ubi_names' from PFI.");
-		goto err;
-	}
-
-	rc = bootenv_list_import(ubi_name_list, tmp_str);
-	if (rc != 0) {
-		EBUF_PFI("Cannot translate PFI value: %s", tmp_str);
-		goto err;
-	}
-	rc = bootenv_list_to_vector(ubi_name_list, &size,
-				    &(tmp_names));
-	res->names_size = size;
-	if (rc != 0) {
-		EBUF_PFI("Cannot create string array: %s", tmp_str);
-		goto err;
-	}
-
-	if (res->names_size != res->ids_size) {
-		EBUF_PFI("Sanity check failed: ubi_ids list does not match "
-			 "sizeof ubi_names list.");
-		rc = -1;
-	}
-
-	/* copy tmp_names to own structure */
-	res->names = (char**) calloc(1, res->names_size * sizeof (char*));
-	if (res->names == NULL)
-		goto err;
-
-	for (i = 0; i < res->names_size; i++) {
-		res->names[i] = calloc(PFI_UBI_VOL_NAME_LEN + 1, sizeof(char));
-		if (res->names[i] == NULL)
-			goto err;
-		strncpy(res->names[i], tmp_names[i], PFI_UBI_VOL_NAME_LEN + 1);
-	}
-
-	goto out;
-
- err:
-	if (res) {
-		if (res->names) {
-			for (i = 0; i < res->names_size; i++) {
-				if (res->names[i]) {
-					free(res->names[i]);
-				}
-			}
-			free(res->names);
-		}
-		if (res->ids) {
-			free(res->ids);
-		}
-		free(res);
-		res = NULL;
-	}
-
- out:
-	bootenv_list_destroy(&ubi_id_list);
-	bootenv_list_destroy(&ubi_name_list);
-	if (tmp_names != NULL)
-		free(tmp_names);
-	*pfi_ubi = res;
-	return rc;
-}
-
-
-int
-free_pdd_data(pdd_data_t* pdd_data)
-{
-	if (*pdd_data) {
-		free(*pdd_data);
-	}
-	*pdd_data = NULL;
-
-	return 0;
-}
-
-int
-free_pfi_raw(pfi_raw_t* pfi_raw)
-{
-	pfi_raw_t tmp = *pfi_raw;
-	if (tmp) {
-		if (tmp->starts)
-			free(tmp->starts);
-		free(tmp);
-	}
-	*pfi_raw = NULL;
-
-	return 0;
-}
-
-int
-free_pfi_ubi(pfi_ubi_t* pfi_ubi)
-{
-	size_t i;
-	pfi_ubi_t tmp = *pfi_ubi;
-	if (tmp) {
-		if (tmp->ids)
-			free(tmp->ids);
-		if (tmp->names) {
-			for (i = 0; i < tmp->names_size; i++) {
-				if (tmp->names[i]) {
-					free(tmp->names[i]);
-				}
-			}
-			free(tmp->names);
-		}
-		free(tmp);
-	}
-	*pfi_ubi = NULL;
-
-	return 0;
-}
-
-
-int
-read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi,
-		 char* err_buf, size_t err_buf_size)
-{
-	int rc = 0;
-	char mode[PFI_KEYWORD_LEN];
-	char label[PFI_LABEL_LEN];
-
-	*pfi_raws = mk_empty(); pfi_raw_t raw = NULL;
-	*pfi_ubis = mk_empty(); pfi_ubi_t ubi = NULL;
-	pfi_header pfi_header = NULL;
-
-	/* read all headers from PFI and store them in lists */
-	rc = pfi_header_init(&pfi_header);
-	if (rc != 0) {
-		EBUF("Cannot initialize pfi header.");
-		goto err;
-	}
-	while ((rc == 0) && !feof(fp_pfi)) {
-		rc = pfi_header_read(fp_pfi, pfi_header);
-		if (rc != 0) {
-			if (rc == PFI_DATA_START) {
-				rc = 0;
-				break; /* data section starts,
-					  all headers read */
-			}
-			else {
-				goto err;
-			}
-		}
-		rc = pfi_header_getstring(pfi_header, "label", label,
-					  PFI_LABEL_LEN);
-		if (rc != 0) {
-			EBUF("Cannot read 'label' from PFI.");
-			goto err;
-		}
-		rc = pfi_header_getstring(pfi_header, "mode", mode,
-					  PFI_KEYWORD_LEN);
-		if (rc != 0) {
-			EBUF("Cannot read 'mode' from PFI.");
-			goto err;
-		}
-		if (strcmp(mode, "ubi") == 0) {
-			rc = read_pfi_ubi(pfi_header, fp_pfi, &ubi, label,
-					  err_buf, err_buf_size);
-			if (rc != 0) {
-				goto err;
-			}
-			*pfi_ubis = append_elem(ubi, *pfi_ubis);
-		}
-		else if (strcmp(mode, "raw") == 0) {
-			rc = read_pfi_raw(pfi_header, fp_pfi, &raw, label,
-					  err_buf, err_buf_size);
-			if (rc != 0) {
-				goto err;
-			}
-			*pfi_raws = append_elem(raw, *pfi_raws);
-		}
-		else {
-			EBUF("Recvieved unknown mode from PFI: %s", mode);
-			goto err;
-		}
-	}
-	goto out;
-
- err:
-	*pfi_raws = remove_all((free_func_t)&free_pfi_raw, *pfi_raws);
-	*pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, *pfi_ubis);
- out:
-	pfi_header_destroy(&pfi_header);
-	return rc;
-
-}
diff --git a/ubi-utils/src/reader.h b/ubi-utils/src/reader.h
deleted file mode 100644
index 715e464..0000000
--- a/ubi-utils/src/reader.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef __READER_H__
-#define __READER_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: Oliver Lohmann
- *
- * Read Platform Description Data (PDD).
- */
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include "pfi.h"
-#include "bootenv.h"
-#include "list.h"
-
-typedef enum flash_type_t {
-	NAND_FLASH = 0,
-	NOR_FLASH,
-} flash_type_t;
-
-typedef struct pdd_data *pdd_data_t;
-typedef struct pfi_raw	*pfi_raw_t;
-typedef struct pfi_ubi	*pfi_ubi_t;
-
-struct pdd_data {
-	uint32_t flash_size;
-	uint32_t flash_page_size;
-	uint32_t eb_size;
-	uint32_t vid_hdr_offset;
-	flash_type_t flash_type;
-};
-
-struct pfi_raw {
-	uint32_t data_size;
-	uint32_t *starts;
-	uint32_t starts_size;
-	uint32_t crc;
-};
-
-struct pfi_ubi {
-	uint32_t data_size;
-	uint32_t alignment;
-	uint32_t *ids;
-	uint32_t ids_size;
-	char	 **names;
-	uint32_t names_size;
-	uint32_t size;
-	enum { pfi_ubi_dynamic, pfi_ubi_static } type;
-	int curr_seqnum; /* specifies the seqnum taken in an update,
-			    default: 0 (used by pfiflash, ubimirror) */
-	uint32_t crc;
-};
-
-int read_pdd_data(FILE* fp_pdd, pdd_data_t *pdd_data,
-		char *err_buf, size_t err_buf_size);
-int read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi, pfi_raw_t *pfi_raw,
-		const char *label, char *err_buf, size_t err_buf_size);
-int read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi, pfi_ubi_t *pfi_ubi,
-		const char *label, char *err_buf, size_t err_buf_size);
-
-/**
- * @brief Reads all pfi headers into list structures, separated by
- *	  RAW and UBI sections.
- */
-int read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi,
-		char* err_buf, size_t err_buf_size);
-int free_pdd_data(pdd_data_t *pdd_data);
-int free_pfi_raw(pfi_raw_t *raw_pfi);
-int free_pfi_ubi(pfi_ubi_t *pfi_ubi);
-
-#endif /* __READER_H__ */
diff --git a/ubi-utils/src/ubiattach.c b/ubi-utils/src/ubiattach.c
new file mode 100644
index 0000000..1f72620
--- /dev/null
+++ b/ubi-utils/src/ubiattach.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to attach MTD devices to UBI.
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME    "ubiattach"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int devn;
+	int mtdn;
+	int vidoffs;
+	const char *node;
+};
+
+static struct args args = {
+	.devn = UBI_DEV_NUM_AUTO,
+	.mtdn = -1,
+	.vidoffs = 0,
+	.node = NULL,
+};
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+			 " - a tool to attach MTD device to UBI.";
+
+static const char *optionsstr =
+"-d, --devn=<UBI device number>  the number to assign to the newly created UBI device\n"
+"                                (the number is assigned automatically if this is not\n"
+"                                specified\n"
+"-m, --mtdn=<MTD device number>  MTD device number to attach\n"
+"-O, --vid-hdr-offset            VID header offset (do not specify this unless you\n"
+"                                really know what you do and the optimal defaults will\n"
+"                                be used)\n"
+"-h, --help                      print help message\n"
+"-V, --version                   print program version";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME " <UBI control device node file name> [-m <MTD device number>] [-d <UBI device number>]\n"
+"\t\t[--mtdn=<MTD device number>] [--devn <UBI device number>]\n"
+"Example 1: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 - attach MTD device 0 (mtd0) to UBI\n"
+"Example 2: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 -d 3 - attach MTD device 0 (mtd0) to UBI and\n"
+"           and create UBI device number 3 (ubi3)";
+
+static const struct option long_options[] = {
+	{ .name = "devn",           .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ .name = "mtdn",           .has_arg = 1, .flag = NULL, .val = 'm' },
+	{ .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
+	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key;
+		char *endp;
+
+		key = getopt_long(argc, argv, "m:d:O:hV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'd':
+			args.devn = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.devn < 0)
+				return errmsg("bad UBI device number: \"%s\"", optarg);
+
+			break;
+
+		case 'm':
+			args.mtdn = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.mtdn < 0)
+				return errmsg("bad MTD device number: \"%s\"", optarg);
+
+			break;
+
+		case 'O':
+			args.vidoffs = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.vidoffs <= 0)
+				return errmsg("bad VID header offset: \"%s\"", optarg);
+
+			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 ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc)
+		return errmsg("UBI control device name was not specified (use -h for help)");
+	else if (optind != argc - 1)
+		return errmsg("more then one UBI control device specified (use -h for help)");
+
+	if (args.mtdn == -1)
+		return errmsg("MTD device number was not specified (use -h for help)");
+
+	args.node = argv[optind];
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+	struct ubi_info ubi_info;
+	struct ubi_dev_info dev_info;
+	struct ubi_attach_request req;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libubi = libubi_open(1);
+	if (libubi == NULL)
+		return sys_errmsg("cannot open libubi");
+
+	/*
+	 * Make sure the kernel is fresh enough and this feature is supported.
+	 */
+	err = ubi_get_info(libubi, &ubi_info);
+	if (err) {
+		sys_errmsg("cannot get UBI information");
+		goto out_libubi;
+	}
+
+	if (ubi_info.ctrl_major == -1) {
+		errmsg("MTD attach/detach feature is not supported by your kernel");
+		goto out_libubi;
+	}
+
+	req.dev_num = args.devn;
+	req.mtd_num = args.mtdn;
+	req.vid_hdr_offset = args.vidoffs;
+
+	err = ubi_attach_mtd(libubi, args.node, &req);
+	if (err) {
+		sys_errmsg("cannot attach mtd%d", args.mtdn);
+		goto out_libubi;
+	}
+
+	/* Print some information about the new UBI device */
+	err = ubi_get_dev_info1(libubi, req.dev_num, &dev_info);
+	if (err) {
+		sys_errmsg("cannot get information about newly created UBI device");
+		goto out_libubi;
+	}
+
+	printf("UBI device number %d, total %d LEBs (", dev_info.dev_num, dev_info.total_lebs);
+	ubiutils_print_bytes(dev_info.total_bytes, 0);
+	printf("), available %d LEBs (", dev_info.avail_lebs);
+	ubiutils_print_bytes(dev_info.avail_bytes, 0);
+	printf("), LEB size ");
+	ubiutils_print_bytes(dev_info.leb_size, 1);
+	printf("\n");
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/src/ubicrc32.c
new file mode 100644
index 0000000..d39af10
--- /dev/null
+++ b/ubi-utils/src/ubicrc32.c
@@ -0,0 +1,124 @@
+/*
+ * 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 <unistd.h>
+#include <mtd/ubi-media.h>
+
+#include "crc32.h"
+#include "common.h"
+
+#define BUFSIZE 4096
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME    "ubicrc32"
+
+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/src/ubidetach.c
new file mode 100644
index 0000000..50670d0
--- /dev/null
+++ b/ubi-utils/src/ubidetach.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to delete UBI devices (detach MTD devices from UBI).
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME    "ubidetach"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int devn;
+	int mtdn;
+	const char *node;
+};
+
+static struct args args = {
+	.devn = UBI_DEV_NUM_AUTO,
+	.mtdn = -1,
+	.node = NULL,
+};
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+" - a tool to remove UBI devices (detach MTD devices from UBI)";
+
+static const char *optionsstr =
+"-d, --devn=<UBI device number>  UBI device number to delete\n"
+"-m, --mtdn=<MTD device number>  or altrnatively, MTD device number to detach -\n"
+"                                this will delete corresponding UBI device\n"
+"-h, --help                      print help message\n"
+"-V, --version                   print program version";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME "<UBI control device node file name> [-d <UBI device number>] [-m <MTD device number>]\n"
+"\t\t[--devn <UBI device number>] [--mtdn=<MTD device number>]\n"
+"Example 1: " PROGRAM_NAME " /dev/ubi_ctrl -d 2 - delete UBI device 2 (ubi2)\n"
+"Example 2: " PROGRAM_NAME " /dev/ubi_ctrl -m 0 - detach MTD device 0 (mtd0)";
+
+static const struct option long_options[] = {
+	{ .name = "devn",    .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ .name = "mtdn",    .has_arg = 1, .flag = NULL, .val = 'm' },
+	{ .name = "help",    .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key;
+		char *endp;
+
+		key = getopt_long(argc, argv, "m:d:hV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'd':
+			args.devn = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.devn < 0)
+				return errmsg("bad UBI device number: \"%s\"", optarg);
+
+			break;
+
+		case 'm':
+			args.mtdn = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.mtdn < 0)
+				return errmsg("bad MTD device number: \"%s\"", optarg);
+
+			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 ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc)
+		return errmsg("UBI control device name was not specified (use -h for help)");
+	else if (optind != argc - 1)
+		return errmsg("more then one UBI control device specified (use -h for help)");
+
+	if (args.mtdn == -1 && args.devn == -1)
+		return errmsg("neither MTD nor UBI devices were specified (use -h for help)");
+
+	if (args.mtdn != -1 && args.devn != -1)
+		return errmsg("specify either MTD or UBI device (use -h for help)");
+
+	args.node = argv[optind];
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+	struct ubi_info ubi_info;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libubi = libubi_open(1);
+	if (libubi == NULL)
+		return sys_errmsg("cannot open libubi");
+
+	/*
+	 * Make sure the kernel is fresh enough and this feature is supported.
+	 */
+	err = ubi_get_info(libubi, &ubi_info);
+	if (err) {
+		sys_errmsg("cannot get UBI information");
+		goto out_libubi;
+	}
+
+	if (ubi_info.ctrl_major == -1) {
+		errmsg("MTD detach/detach feature is not supported by your kernel");
+		goto out_libubi;
+	}
+
+	if (args.devn != -1) {
+		err = ubi_remove_dev(libubi, args.node, args.devn);
+		if (err) {
+			sys_errmsg("cannot remove ubi%d", args.devn);
+			goto out_libubi;
+		}
+	} else {
+		err = ubi_detach_mtd(libubi, args.node, args.mtdn);
+		if (err) {
+			sys_errmsg("cannot detach mtd%d", args.mtdn);
+			goto out_libubi;
+		}
+	}
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
+
diff --git a/ubi-utils/src/ubiformat.c b/ubi-utils/src/ubiformat.c
new file mode 100644
index 0000000..0074c7a
--- /dev/null
+++ b/ubi-utils/src/ubiformat.c
@@ -0,0 +1,780 @@
+/*
+ * 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.
+ */
+
+/*
+ * An utility to format MTD devices into UBI and flash UBI images.
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <fcntl.h>
+
+#include <libubi.h>
+#include <libmtd.h>
+#include <libscan.h>
+#include <libubigen.h>
+#include <mtd_swab.h>
+#include "crc32.h"
+#include "common.h"
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME    "ubiformat"
+
+/* The variables below are set by command line arguments */
+struct args {
+	unsigned int yes:1;
+	unsigned int quiet:1;
+	unsigned int verbose:1;
+	unsigned int override_ec:1;
+	unsigned int novtbl:1;
+	int subpage_size;
+	int vid_hdr_offs;
+	int ubi_ver;
+	off_t image_sz;
+	long long ec;
+	const char *image;
+	const char *node;
+};
+
+static struct args args =
+{
+	.ubi_ver = 1,
+};
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+		" - a tool to format MTD devices and flash UBI images";
+
+static const char *optionsstr =
+"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
+"                             headers, e.g. sub-page size in case of NAND\n"
+"                             flash (equivalent to the minimum input/output\n"
+"                             unit size by default)\n"
+"-O, --vid-hdr-offset=<offs>  offset if the VID header from start of the\n"
+"                             physical eraseblock (default is the next\n"
+"                             minimum I/O unit or sub-page after the EC\n"
+"                             header)\n"
+"-n, --no-volume-table        only erase all eraseblock and preserve erase\n"
+"                             counters, do not write empty volume table\n"
+"-f, --flash-image=<file>     flash image file, or '-' for stdin\n"
+"-S, --image-size=<bytes>     bytes in input, if not reading from file\n"
+"-e, --erase-counter=<value>  use <value> as the erase counter value for all\n"
+"                             eraseblocks\n"
+"-y, --yes                    assume the answer is \"yes\" for all question\n"
+"                             this program would otherwise ask\n"
+"-q, --quiet                  suppress progress percentage information\n"
+"-v, --verbose                be verbose\n"
+"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
+"                             (default is 1)\n"
+"-h, -?, --help               print help message\n"
+"-V, --version                print program version\n";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME " <MTD device node file name> [-h] [-V] [-y] [-q] [-v]\n"
+"\t\t\t[-x <num>] [-E <value>] [-s <bytes>] [-O <offs>] [-n]\n"
+"\t\t\t[--help] [--version] [--yes] [--verbose] [--quiet]\n"
+"\t\t\t[--ec=<value>] [--vid-hdr-offset=<offs>]\n"
+"\t\t\t[--ubi-ver=<num>] [--no-volume-table]\n"
+"\t\t\t[--flash-image=<file>] [--image-size=<bytes>]\n\n"
+
+"Example 1: " PROGRAM_NAME " /dev/mtd0 -y - format MTD device number 0 and do\n"
+"           not ask questions.\n"
+"Example 2: " PROGRAM_NAME " /dev/mtd0 -q -e 0 - format MTD device number 0,\n"
+"           be quiet and force erase counter value 0.";
+
+static const struct option long_options[] = {
+	{ .name = "sub-page-size",   .has_arg = 1, .flag = NULL, .val = 's' },
+	{ .name = "vid-hdr-offset",  .has_arg = 1, .flag = NULL, .val = 'O' },
+	{ .name = "no-volume-table", .has_arg = 0, .flag = NULL, .val = 'n' },
+	{ .name = "flash-image",     .has_arg = 1, .flag = NULL, .val = 'f' },
+	{ .name = "image-size",      .has_arg = 1, .flag = NULL, .val = 'S' },
+	{ .name = "yes",             .has_arg = 0, .flag = NULL, .val = 'y' },
+	{ .name = "erase-counter",   .has_arg = 1, .flag = NULL, .val = 'e' },
+	{ .name = "quiet",           .has_arg = 0, .flag = NULL, .val = 'q' },
+	{ .name = "verbose",         .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "ubi-ver",         .has_arg = 1, .flag = NULL, .val = 'x' },
+	{ .name = "help",            .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",         .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key;
+		char *endp;
+
+		key = getopt_long(argc, argv, "nh?Vyqve:x:s:O:f:S:", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 's':
+			args.subpage_size = ubiutils_get_bytes(optarg);
+			if (args.subpage_size <= 0)
+				return errmsg("bad sub-page size: \"%s\"", optarg);
+			if (!is_power_of_2(args.subpage_size))
+				return errmsg("sub-page size should be power of 2");
+			break;
+
+		case 'O':
+			args.vid_hdr_offs = strtoul(optarg, &endp, 0);
+			if (args.vid_hdr_offs <= 0 || *endp != '\0' || endp == optarg)
+				return errmsg("bad VID header offset: \"%s\"", optarg);
+			break;
+
+		case 'e':
+			args.ec = strtoull(optarg, &endp, 0);
+			if (args.ec <= 0 || *endp != '\0' || endp == optarg)
+				return errmsg("bad erase counter value: \"%s\"", optarg);
+			if (args.ec >= EC_MAX)
+				return errmsg("too high erase %llu, counter, max is %u", args.ec, EC_MAX);
+			args.override_ec = 1;
+			break;
+
+		case 'f':
+			args.image = optarg;
+			break;
+
+		case 'S':
+			args.image_sz = ubiutils_get_bytes(optarg);
+			if (args.image_sz <= 0)
+				return errmsg("bad image-size: \"%s\"", optarg);
+			break;
+
+		case 'n':
+			args.novtbl = 1;
+			break;
+
+		case 'y':
+			args.yes = 1;
+			break;
+
+		case 'q':
+			args.quiet = 1;
+			break;
+
+		case 'x':
+			args.ubi_ver = strtoul(optarg, &endp, 0);
+			if (args.ubi_ver < 0 || *endp != '\0' || endp == optarg)
+				return errmsg("bad UBI version: \"%s\"", optarg);
+			break;
+
+		case 'v':
+			args.verbose = 1;
+			break;
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case 'h':
+		case '?':
+			fprintf(stderr, "%s\n\n", doc);
+			fprintf(stderr, "%s\n\n", usage);
+			fprintf(stderr, "%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (args.quiet && args.verbose)
+		return errmsg("using \"-q\" and \"-v\" at the same time does not make sense");
+
+	if (optind == argc)
+		return errmsg("MTD device name was not specified (use -h for help)");
+	else if (optind != argc - 1)
+		return errmsg("more then one MTD device specified (use -h for help)");
+
+	if (args.image && args.novtbl)
+		return errmsg("-n cannot be used together with -f");
+
+	args.node = argv[optind];
+	return 0;
+}
+
+static int want_exit(void)
+{
+	char buf[4];
+
+	while (1) {
+		normsg_cont("continue? (yes/no)  ");
+		if (scanf("%3s", buf) == EOF) {
+			sys_errmsg("scanf returned unexpected EOF, assume \"yes\"");
+			return 1;
+		}
+		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))
+			return 0;
+		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))
+			return 1;
+	}
+}
+
+static int answer_is_yes(void)
+{
+	char buf[4];
+
+	while (1) {
+		if (scanf("%3s", buf) == EOF) {
+			sys_errmsg("scanf returned unexpected EOF, assume \"no\"");
+			return 0;
+		}
+		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))
+			return 1;
+		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))
+			return 0;
+	}
+}
+
+static void print_bad_eraseblocks(const struct mtd_info *mtd,
+				  const struct ubi_scan_info *si)
+{
+	int first = 1, eb;
+
+	if (si->bad_cnt == 0)
+		return;
+
+	normsg_cont("bad eraseblocks: ");
+	for (eb = 0; eb < mtd->eb_cnt; eb++) {
+		if (si->ec[eb] != EB_BAD)
+			continue;
+		if (first) {
+			printf("%d", eb);
+			first = 0;
+		} else
+			printf(", %d", eb);
+	}
+	printf("\n");
+}
+
+static int change_ec(struct ubi_ec_hdr *hdr, long long ec)
+{
+	uint32_t crc;
+
+	/* Check the EC header */
+	if (be32_to_cpu(hdr->magic) != UBI_EC_HDR_MAGIC)
+		return errmsg("bad UBI magic %#08x, should be %#08x",
+			      be32_to_cpu(hdr->magic), UBI_EC_HDR_MAGIC);
+
+	crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	if (be32_to_cpu(hdr->hdr_crc) != crc)
+		return errmsg("bad CRC %#08x, should be %#08x\n",
+			      crc, be32_to_cpu(hdr->hdr_crc));
+
+	hdr->ec = cpu_to_be64(ec);
+	crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
+
+	return 0;
+}
+
+static int drop_ffs(const struct mtd_info *mtd, const void *buf, int len)
+{
+	int i;
+
+        for (i = len - 1; i >= 0; i--)
+		if (((const uint8_t *)buf)[i] != 0xFF)
+		      break;
+
+        /* The resulting length must be aligned to the minimum flash I/O size */
+        len = i + 1;
+	len = (len + mtd->min_io_size - 1) / mtd->min_io_size;
+	len *=  mtd->min_io_size;
+        return len;
+}
+
+static int open_file(off_t *sz)
+{
+	int fd;
+
+	if (!strcmp(args.image, "-")) {
+		if (args.image_sz == 0)
+			return errmsg("must use '-S' with non-zero value when reading from stdin");
+
+		*sz = args.image_sz;
+		fd  = dup(STDIN_FILENO);
+		if (fd < 0)
+			return sys_errmsg("failed to dup stdin");
+	} else {
+		struct stat st;
+
+		if (stat(args.image, &st))
+			return sys_errmsg("cannot open \"%s\"", args.image);
+
+		*sz = st.st_size;
+		fd  = open(args.image, O_RDONLY);
+		if (fd == -1)
+			return sys_errmsg("cannot open \"%s\"", args.image);
+	}
+
+	return fd;
+}
+
+static int read_all(int fd, void *buf, size_t len)
+{
+	while (len > 0) {
+		ssize_t l = read(fd, buf, len);
+		if (l == 0)
+			return errmsg("eof reached; %zu bytes remaining", len);
+		else if (l > 0) {
+			buf += l;
+			len -= l;
+		} else if (errno == EINTR || errno == EAGAIN)
+			continue;
+		else
+			return sys_errmsg("reading failed; %zu bytes remaining", len);
+	}
+
+	return 0;
+}
+
+static int flash_image(const struct mtd_info *mtd, struct ubi_scan_info *si)
+{
+	int fd, img_ebs, eb, written_ebs = 0, divisor;
+	off_t st_size;
+
+	fd = open_file(&st_size);
+	if (fd < 0)
+		return fd;
+
+	img_ebs = st_size / mtd->eb_size;
+
+	if (img_ebs > si->good_cnt) {
+		sys_errmsg("file \"%s\" is too large (%lld bytes)",
+			   args.image, (long long)st_size);
+		goto out_close;
+	}
+
+	if (st_size % mtd->eb_size) {
+		return sys_errmsg("file \"%s\" (size %lld bytes) is not multiple of eraseblock size (%d bytes)",
+				  args.image, (long long)st_size, mtd->eb_size);
+		goto out_close;
+	}
+
+	verbose(args.verbose, "will write %d eraseblocks", img_ebs);
+	divisor = img_ebs;
+	for (eb = 0; eb < mtd->eb_cnt; eb++) {
+		int err, new_len;
+		char buf[mtd->eb_size];
+		long long ec;
+
+		if (!args.quiet && !args.verbose) {
+			printf("\r" PROGRAM_NAME ": flashing eraseblock %d -- %2lld %% complete  ",
+			       eb, (long long)(eb + 1) * 100 / divisor);
+			fflush(stdout);
+		}
+
+		if (si->ec[eb] == EB_BAD) {
+			divisor += 1;
+			continue;
+		}
+
+		if (args.verbose) {
+			normsg_cont("eraseblock %d: erase", eb);
+			fflush(stdout);
+		}
+
+		err = mtd_erase(mtd, eb);
+		if (err) {
+			sys_errmsg("failed to erase eraseblock %d", eb);
+			goto out_close;
+		}
+
+		err = read_all(fd, buf, mtd->eb_size);
+		if (err) {
+			sys_errmsg("failed to read eraseblock %d from \"%s\"",
+				   written_ebs, args.image);
+			goto out_close;
+		}
+
+
+		if (si->ec[eb] <= EC_MAX)
+			ec = si->ec[eb] + 1;
+		else if (!args.override_ec)
+			ec = si->mean_ec;
+		else
+			ec = args.ec;
+
+		if (args.verbose) {
+			printf(", change EC to %lld", ec);
+			fflush(stdout);
+		}
+
+		err = change_ec((struct ubi_ec_hdr *)buf, ec);
+		if (err) {
+			errmsg("bad EC header at eraseblock %d of \"%s\"",
+			       written_ebs, args.image);
+			goto out_close;
+		}
+
+		if (args.verbose) {
+			printf(", write data\n");
+			fflush(stdout);
+		}
+
+		new_len = drop_ffs(mtd, buf, mtd->eb_size);
+
+		err = mtd_write(mtd, eb, 0, buf, new_len);
+		if (err) {
+			sys_errmsg("cannot write eraseblock %d", eb);
+			goto out_close;
+		}
+		if (++written_ebs >= img_ebs)
+			break;
+	}
+
+	if (!args.quiet && !args.verbose)
+		printf("\n");
+	close(fd);
+	return eb + 1;
+
+out_close:
+	close(fd);
+	return -1;
+}
+
+static int format(const struct mtd_info *mtd, const struct ubigen_info *ui,
+		  const struct ubi_scan_info *si, int start_eb, int novtbl)
+{
+	int eb, err, write_size;
+	struct ubi_ec_hdr *hdr;
+	struct ubi_vtbl_record *vtbl;
+	int eb1 = -1, eb2 = -1;
+	long long ec1 = -1, ec2 = -1;
+
+	write_size = UBI_EC_HDR_SIZE + mtd->subpage_size - 1;
+	write_size /= mtd->subpage_size;
+	write_size *= mtd->subpage_size;
+	hdr = malloc(write_size);
+	if (!hdr)
+		return sys_errmsg("cannot allocate %d bytes of memory", write_size);
+
+	memset(hdr, 0xFF, write_size);
+
+	for (eb = start_eb; eb < mtd->eb_cnt; eb++) {
+		long long ec;
+
+		if (!args.quiet && !args.verbose) {
+			printf("\r" PROGRAM_NAME ": formatting eraseblock %d -- %2lld %% complete  ",
+			       eb, (long long)(eb + 1 - start_eb) * 100 / (mtd->eb_cnt - start_eb));
+			fflush(stdout);
+		}
+
+		if (si->ec[eb] == EB_BAD)
+			continue;
+
+		if (si->ec[eb] <= EC_MAX)
+			ec = si->ec[eb] + 1;
+		else if (!args.override_ec)
+			ec = si->mean_ec;
+		else
+			ec = args.ec;
+		ubigen_init_ec_hdr(ui, hdr, ec);
+
+		if (args.verbose) {
+			normsg_cont("eraseblock %d: erase", eb);
+			fflush(stdout);
+		}
+
+		err = mtd_erase(mtd, eb);
+		if (err) {
+			if (!args.quiet)
+				printf("\n");
+			sys_errmsg("failed to erase eraseblock %d", eb);
+			goto out_free;
+		}
+
+		if ((eb1 == -1 || eb2 == -1) && !novtbl) {
+			if (eb1 == -1) {
+				eb1 = eb;
+				ec1 = ec;
+			} else if (eb2 == -1) {
+				eb2 = eb;
+				ec2 = ec;
+			}
+			if (args.verbose)
+				printf(", do not write EC, leave for vtbl\n");
+			continue;
+		}
+
+		if (args.verbose) {
+			printf(", write EC %lld\n", ec);
+			fflush(stdout);
+		}
+
+		err = mtd_write(mtd, eb, 0, hdr, write_size);
+		if (err) {
+			if (!args.quiet && !args.verbose)
+				printf("\n");
+			sys_errmsg("cannot write EC header (%d bytes buffer) to eraseblock %d",
+				   write_size, eb);
+			if (args.subpage_size != mtd->min_io_size)
+				normsg("may be %d is incorrect?", args.subpage_size);
+			goto out_free;
+		}
+	}
+
+	if (!args.quiet && !args.verbose)
+		printf("\n");
+
+	if (!novtbl) {
+		if (eb1 == -1 || eb2 == -1) {
+			errmsg("no eraseblocks for volume table");
+			goto out_free;
+		}
+
+		verbose(args.verbose, "write volume table to eraseblocks %d and %d", eb1, eb2);
+		vtbl = ubigen_create_empty_vtbl(ui);
+		if (!vtbl)
+			goto out_free;
+
+		err = ubigen_write_layout_vol(ui, eb1, eb2, ec1,  ec2, vtbl, mtd->fd);
+		free(vtbl);
+		if (err) {
+			errmsg("cannot write layout volume");
+			goto out_free;
+		}
+	}
+
+	free(hdr);
+	return 0;
+
+out_free:
+	free(hdr);
+	return -1;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err, verbose;
+	struct mtd_info mtd;
+	libubi_t libubi;
+	struct ubigen_info ui;
+	struct ubi_scan_info *si;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	err = mtd_get_info(args.node, &mtd);
+	if (err)
+		return errmsg("cannot get information about \"%s\"", args.node);
+
+	if (args.subpage_size == 0)
+		args.subpage_size = mtd.min_io_size;
+	else {
+		if (args.subpage_size > mtd.min_io_size) {
+			errmsg("sub-page cannot be larger than min. I/O unit");
+			goto out_close;
+		}
+
+		if (mtd.min_io_size % args.subpage_size) {
+			errmsg("min. I/O unit size should be multiple of sub-page size");
+			goto out_close;
+		}
+	}
+
+	/* Validate VID header offset if it was specified */
+	if (args.vid_hdr_offs != 0) {
+		if (args.vid_hdr_offs % 8) {
+			errmsg("VID header offset has to be multiple of min. I/O unit size");
+			goto out_close;
+		}
+		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE > mtd.eb_size) {
+			errmsg("bad VID header offset");
+			goto out_close;
+		}
+	}
+
+	/*
+	 * Because of MTD interface limitations 'mtd_get_info()' cannot get
+	 * sub-page so we force the user to pass it via the command line. Let's
+	 * hope the user passed us something sane.
+	 */
+	mtd.subpage_size = args.subpage_size;
+
+	if (mtd.rdonly) {
+		errmsg("mtd%d (%s) is a read-only device", mtd.num, args.node);
+		goto out_close;
+	}
+
+	/* Make sure this MTD device is not attached to UBI */
+	libubi = libubi_open(0);
+	if (libubi) {
+		int ubi_dev_num;
+
+		err = mtd_num2ubi_dev(libubi, mtd.num, &ubi_dev_num);
+		libubi_close(libubi);
+		if (!err) {
+			errmsg("please, first detach mtd%d (%s) from ubi%d",
+			       mtd.num, args.node, ubi_dev_num);
+			goto out_close;
+		}
+	}
+
+	if (!args.quiet) {
+		normsg_cont("mtd%d (%s), size ", mtd.num, mtd.type_str);
+		ubiutils_print_bytes(mtd.size, 1);
+		printf(", %d eraseblocks of ", mtd.eb_size);
+		ubiutils_print_bytes(mtd.eb_size, 1);
+		printf(", min. I/O size %d bytes\n", mtd.min_io_size);
+	}
+
+	if (args.quiet)
+		verbose = 0;
+	else if (args.verbose)
+		verbose = 2;
+	else
+		verbose = 1;
+	err = ubi_scan(&mtd, &si, verbose);
+	if (err) {
+		errmsg("failed to scan mtd%d (%s)", mtd.num, args.node);
+		goto out_close;
+	}
+
+	if (si->good_cnt == 0) {
+		errmsg("all %d eraseblocks are bad", si->bad_cnt);
+		goto out_free;
+	}
+
+	if (si->good_cnt < 2 && (!args.novtbl || args.image)) {
+		errmsg("too few non-bad eraseblocks (%d) on mtd%d", si->good_cnt, mtd.num);
+		goto out_free;
+	}
+
+	if (!args.quiet) {
+		if (si->ok_cnt)
+			normsg("%d eraseblocks have valid erase counter, mean value is %lld",
+			       si->ok_cnt, si->mean_ec);
+		if (si->empty_cnt)
+			normsg("%d eraseblocks are supposedly empty", si->empty_cnt);
+		if (si->corrupted_cnt)
+			normsg("%d corrupted erase counters", si->corrupted_cnt);
+		print_bad_eraseblocks(&mtd, si);
+	}
+
+	if (si->alien_cnt) {
+		if (!args.yes || !args.quiet)
+			warnmsg("%d of %d eraseblocks contain non-ubifs data",
+				si->alien_cnt, si->good_cnt);
+		if (!args.yes && want_exit()) {
+			if (args.yes && !args.quiet)
+				printf("yes\n");
+			goto out_free;
+		}
+	}
+
+	if (!args.override_ec && si->empty_cnt < si->good_cnt) {
+		int percent = ((double)si->ok_cnt)/si->good_cnt * 100;
+
+		/*
+		 * Make sure the majority of eraseblocks have valid
+		 * erase counters.
+		 */
+		if (percent < 50) {
+			if (!args.yes || !args.quiet)
+				warnmsg("only %d of %d eraseblocks have valid erase counter",
+					si->ok_cnt, si->good_cnt);
+				normsg("erase counter 0 will be used for all eraseblocks");
+				normsg("note, arbitrary erase counter value may be specified using -e option");
+			if (!args.yes && want_exit()) {
+				if (args.yes && !args.quiet)
+					printf("yes\n");
+				goto out_free;
+			}
+			 args.ec = 0;
+			 args.override_ec = 1;
+		} else if (percent < 95) {
+			if (!args.yes || !args.quiet)
+				warnmsg("only %d of %d eraseblocks have valid erase counter",
+					si->ok_cnt, si->good_cnt);
+				normsg("mean erase counter %lld will be used for the rest of eraseblock",
+				       si->mean_ec);
+			if (!args.yes && want_exit()) {
+				if (args.yes && !args.quiet)
+					printf("yes\n");
+				goto out_free;
+			}
+			args.ec = si->mean_ec;
+			args.override_ec = 1;
+		}
+	}
+
+	if (!args.quiet && args.override_ec)
+		normsg("use erase counter %lld for all eraseblocks", args.ec);
+
+	ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, args.subpage_size,
+			 args.vid_hdr_offs, args.ubi_ver);
+
+	if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) {
+		/*
+		 * Hmm, what we read from flash and what we calculated using
+		 * min. I/O unit size and sub-page size differs.
+		 */
+		if (!args.yes || !args.quiet) {
+			warnmsg("VID header and data offsets on flash are %d and %d, "
+				"which is different to calculated offsets %d and %d",
+				si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs,
+				ui.data_offs);
+			normsg_cont("use new offsets %d and %d? (yes/no)  ",
+				    si->vid_hdr_offs, si->data_offs);
+		}
+		if (args.yes || answer_is_yes()) {
+			if (args.yes && !args.quiet)
+				printf("yes\n");
+		} else {
+			ui.vid_hdr_offs = si->vid_hdr_offs;
+			ui.data_offs = si->data_offs;
+		}
+	}
+
+	if (args.image) {
+		err = flash_image(&mtd, si);
+		if (err < 0)
+			goto out_free;
+
+		err = format(&mtd, &ui, si, err, 1);
+		if (err)
+			goto out_free;
+	} else {
+		err = format(&mtd, &ui, si, 0, args.novtbl);
+		if (err)
+			goto out_free;
+	}
+
+	ubi_scan_free(si);
+	close(mtd.fd);
+	return 0;
+
+out_free:
+	ubi_scan_free(si);
+out_close:
+	close(mtd.fd);
+	return -1;
+}
diff --git a/ubi-utils/src/ubigen.c b/ubi-utils/src/ubigen.c
deleted file mode 100644
index bb55fa9..0000000
--- a/ubi-utils/src/ubigen.c
+++ /dev/null
@@ -1,359 +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
- *
- * Tool to add UBI headers to binary images.
- *
- * 1.0 Initial version
- * 1.1 Different CRC32 start value
- * 1.2 Removed argp because we want to use uClibc.
- * 1.3 Minor cleanups
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <mtd/ubi-media.h>
-
-#include "ubigen.h"
-#include "config.h"
-
-#define PROGRAM_VERSION "1.3"
-
-typedef enum action_t {
-	ACT_NORMAL	     = 0x00000001,
-	ACT_BROKEN_UPDATE    = 0x00000002,
-} action_t;
-
-static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
-	"ubigen - a tool for adding UBI information to a binary input file.\n";
-
-static const char *optionsstr =
-" Common settings:\n"
-"  -c, --copyright            Print copyright information.\n"
-"  -d, --debug\n"
-"  -v, --verbose              Print more progress information.\n"
-"\n"
-" UBI Settings:\n"
-"  -A, --alignment=<num>      Set the alignment size to <num> (default 1).\n"
-"                             Values can be specified as bytes, 'ki' or 'Mi'.\n"
-"  -B, --blocksize=<num>      Set the eraseblock size to <num> (default 128\n"
-"                             KiB).\n"
-"                             Values can be specified as bytes, 'ki' or 'Mi'.\n"
-"  -E, --erasecount=<num>     Set the erase count to <num> (default 0)\n"
-"  -I, --id=<num>             The UBI volume id.\n"
-"  -O, --offset=<num>         Offset from start of an erase block to the UBI\n"
-"                             volume header.\n"
-"  -T, --type=<num>           The UBI volume type:\n"
-"                             1 = dynamic, 2 = static\n"
-"  -X, --setver=<num>         Set UBI version number to <num> (default 1)\n"
-"\n"
-" Input/Output:\n"
-"  -i, --infile=<filename>    Read input from file.\n"
-"  -o, --outfile=<filename>   Write output to file (default is stdout).\n"
-"\n"
-" Special options:\n"
-"  -U, --broken-update=<leb>  Create an ubi image which simulates a broken\n"
-"                             update.\n"
-"                             <leb> specifies the logical eraseblock number to\n"
-"                             update.\n"
-"\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: ubigen [-cdv?V] [-A <num>] [-B <num>] [-E <num>] [-I <num>]\n"
-"          [-O <num>] [-T <num>] [-X <num>] [-i <filename>] [-o <filename>]\n"
-"          [-U <leb>] [--copyright] [--debug] [--verbose] [--alignment=<num>]\n"
-"          [--blocksize=<num>] [--erasecount=<num>] [--id=<num>]\n"
-"          [--offset=<num>] [--type=<num>] [--setver=<num>]\n"
-"          [--infile=<filename>] [--outfile=<filename>]\n"
-"          [--broken-update=<leb>] [--help] [--usage] [--version]\n";
-
-struct option long_options[] = {
-	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
-	{ .name = "debug", .has_arg = 0, .flag = NULL, .val = 'd' },
-	{ .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
-	{ .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'A' },
-	{ .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'B' },
-	{ .name = "erasecount", .has_arg = 1, .flag = NULL, .val = 'E' },
-	{ .name = "id", .has_arg = 1, .flag = NULL, .val = 'I' },
-	{ .name = "offset", .has_arg = 1, .flag = NULL, .val = 'O' },
-	{ .name = "type", .has_arg = 1, .flag = NULL, .val = 'T' },
-	{ .name = "setver", .has_arg = 1, .flag = NULL, .val = 'X' },
-	{ .name = "infile", .has_arg = 1, .flag = NULL, .val = 'i' },
-	{ .name = "outfile", .has_arg = 1, .flag = NULL, .val = 'o' },
-	{ .name = "broken-update", .has_arg = 1, .flag = NULL, .val = 'U' },
-	{ .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}
-};
-
-static const char copyright [] __attribute__((unused)) =
-	"Copyright IBM Corp 2006";
-
-#define CHECK_ENDP(option, endp) do {			\
-	if (*endp) {					\
-		fprintf(stderr,				\
-			"Parse error option \'%s\'. "	\
-			"No correct numeric value.\n"	\
-			, option);			\
-		exit(EXIT_FAILURE);			\
-	}						\
-} while(0)
-
-typedef struct myargs {
-	/* common settings */
-	action_t action;
-	int verbose;
-
-	int32_t id;
-	uint8_t type;
-	uint32_t eb_size;
-	uint64_t ec;
-	uint8_t version;
-	uint32_t hdr_offset;
-	uint32_t update_block;
-	uint32_t alignment;
-
-	FILE* fp_in;
-	FILE* fp_out;
-
-	/* special stuff needed to get additional arguments */
-	char *arg1;
-	char **options;			/* [STRING...] */
-} myargs;
-
-
-static int ustrtoul(const char *cp, char **endp, unsigned int base)
-{
-	unsigned long result = strtoul(cp, endp, base);
-
-	switch (**endp) {
-	case 'G':
-		result *= 1024;
-	case 'M':
-		result *= 1024;
-	case 'k':
-	case 'K':
-		result *= 1024;
-	/* "Ki", "ki", "Mi" or "Gi" are to be used. */
-		if ((*endp)[1] == 'i')
-			(*endp) += 2;
-	}
-	return result;
-}
-
-static int
-parse_opt(int argc, char **argv, myargs *args)
-{
-	int err = 0;
-	char* endp;
-
-	while (1) {
-		int key;
-
-		key = getopt_long(argc, argv, "cdvA:B:E:I:O:T:X:i:o:U:?V",
-				long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-			case 'c':
-				fprintf(stderr, "%s\n", copyright);
-				exit(0);
-				break;
-			case 'o': /* output */
-				args->fp_out = fopen(optarg, "wb");
-				if ((args->fp_out) == NULL) {
-					fprintf(stderr, "Cannot open file %s "
-						"for output\n", optarg);
-					exit(1);
-				}
-				break;
-			case 'i': /* input */
-				args->fp_in = fopen(optarg, "rb");
-				if ((args->fp_in) == NULL) {
-					fprintf(stderr, "Cannot open file %s "
-						"for input\n", optarg);
-					exit(1);
-				}
-				break;
-			case 'v': /* verbose */
-				args->verbose = 1;
-				break;
-
-			case 'B': /* eb_size */
-				args->eb_size =
-					(uint32_t)ustrtoul(optarg, &endp, 0);
-				CHECK_ENDP("B", endp);
-				break;
-			case 'E': /* erasecount */
-				args->ec = (uint64_t)strtoul(optarg, &endp, 0);
-				CHECK_ENDP("E", endp);
-				break;
-			case 'I': /* id */
-				args->id = (uint16_t)strtoul(optarg, &endp, 0);
-				CHECK_ENDP("I", endp);
-				break;
-			case 'T': /* type */
-				args->type =
-					(uint16_t)strtoul(optarg, &endp, 0);
-				CHECK_ENDP("T", endp);
-				break;
-			case 'X': /* versionnr */
-				args->version =
-					(uint8_t)strtoul(optarg, &endp, 0);
-				CHECK_ENDP("X", endp);
-				break;
-			case 'O': /* offset for volume hdr */
-				args->hdr_offset =
-					(uint32_t) strtoul(optarg, &endp, 0);
-				CHECK_ENDP("O", endp);
-				break;
-
-			case 'U': /* broken update */
-				args->action = ACT_BROKEN_UPDATE;
-				args->update_block =
-					(uint32_t) strtoul(optarg, &endp, 0);
-				CHECK_ENDP("U", endp);
-				break;
-
-			case '?': /* help */
-				fprintf(stderr, "Usage: ubigen [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);
-		}
-	}
-
-	if (optind < argc) {
-		if (!args->fp_in) {
-			args->fp_in = fopen(argv[optind++], "rb");
-			if ((args->fp_in) == NULL) {
-				fprintf(stderr,	"Cannot open file %s for "
-					"input\n", argv[optind]);
-				exit(1);
-			}
-		}
-	}
-	if (args->id < 0) {
-		err = 1;
-		fprintf(stderr,
-				"Please specify an UBI Volume ID.\n");
-	}
-	if (args->type == 0) {
-		err = 1;
-		fprintf(stderr,
-				"Please specify an UBI Volume type.\n");
-	}
-	if (err) {
-		fprintf(stderr, "%s", usage);
-		exit(1);
-	}
-
-	return 0;
-}
-
-
-int
-main(int argc, char **argv)
-{
-	int rc = 0;
-	ubi_info_t u;
-	struct stat file_info;
-	off_t input_len = 0; /* only used in static volumes */
-
-	myargs args = {
-		.action = ACT_NORMAL,
-		.verbose = 0,
-
-		.id = -1,
-		.type = 0,
-		.eb_size = 0,
-		.update_block = 0,
-		.ec = 0,
-		.version = 0,
-		.hdr_offset = (DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE),
-		.alignment = 1,
-
-		.fp_in = NULL,
-		.fp_out = stdout,
-		/* arguments */
-		.arg1 = NULL,
-		.options = NULL,
-	};
-
-	ubigen_init(); /* Init CRC32 table in ubigen */
-
-	/* parse arguments */
-	parse_opt(argc, argv, &args);
-
-	if (fstat(fileno(args.fp_in), &file_info) != 0) {
-		fprintf(stderr, "Cannot fetch file size "
-				"from input file.\n");
-	}
-	input_len = file_info.st_size;
-
-	rc = ubigen_create(&u, (uint32_t)args.id, args.type,
-			args.eb_size, args.ec, args.alignment,
-			args.version, args.hdr_offset, 0 ,input_len,
-			args.fp_in, args.fp_out);
-
-	if  (rc != 0) {
-		fprintf(stderr, "Cannot create UBI info handler rc: %d\n", rc);
-		exit(EXIT_FAILURE);
-	}
-
-	if (!args.fp_in || !args.fp_out) {
-		fprintf(stderr, "Input/Output error.\n");
-		exit(EXIT_FAILURE);
-
-	}
-
-	if (args.action & ACT_NORMAL) {
-		rc = ubigen_write_complete(u);
-	}
-	else if (args.action & ACT_BROKEN_UPDATE) {
-		rc = ubigen_write_broken_update(u, args.update_block);
-	}
-	if  (rc != 0) {
-		fprintf(stderr, "Error converting input data.\n");
-		exit(EXIT_FAILURE);
-	}
-
-	rc = ubigen_destroy(&u);
-	return rc;
-}
diff --git a/ubi-utils/src/ubigen.h b/ubi-utils/src/ubigen.h
deleted file mode 100644
index 8d29120..0000000
--- a/ubi-utils/src/ubigen.h
+++ /dev/null
@@ -1,149 +0,0 @@
-#ifndef __UBIGEN_H__
-#define __UBIGEN_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: Frank Haverkamp
- *
- * An utility to update UBI volumes.
- */
-
-#include <stdio.h> /* FILE */
-#include <stdint.h>
-#include <mtd/ubi-media.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define DEFAULT_BLOCKSIZE	(128 * 1024)
-#define DEFAULT_PAGESIZE	(2*1024)
-
-#define EUBIGEN_INVALID_TYPE		1
-#define EUBIGEN_INVALID_HDR_OFFSET	2
-#define EUBIGEN_INVALID_ALIGNMENT	3
-#define EUBIGEN_TOO_SMALL_EB		4
-#define EUBIGEN_MAX_ERROR		5
-
-
-typedef enum action {
-	NO_ERROR	 = 0x00000000,
-	BROKEN_HDR_CRC	 = 0x00000001,
-	BROKEN_DATA_CRC	 = 0x00000002,
-	BROKEN_DATA_SIZE = 0x00000004,
-	BROKEN_OMIT_BLK	 = 0x00000008,
-	MARK_AS_UPDATE	 = 0x00000010,
-} ubigen_action_t;
-
-typedef struct ubi_info *ubi_info_t;
-
-/**
- * @brief	  Initialize the internal CRC32 table.
- * @note	  Necessary because of the used crc32 function in UBI.
- *		  A usage of CRC32, from e.g. zlib will fail.
- */
-void ubigen_init(void);
-
-/**
- * @brief	  Create an ubigen handle.
- * @param  ...
- * @return 0	  On sucess.
- *	   else	  Error.
- * @note	  This parameterlist is ugly. But we have to use
- *		  two big structs and meta information internally,
- *		  filling them would be even uglier.
- */
-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);
-
-/**
- * @brief	  Destroy an ubigen handle.
- * @param  u	  Handle to free.
- * @return 0	  On success.
- *	   else	  Error.
- */
-int ubigen_destroy(ubi_info_t *u);
-
-/**
- * @brief	  Get number of total logical EBs, necessary for the
- *		  complete storage of data in the handle.
- * @param  u	  The handle.
- * @return 0	  On success.
- *	   else	  Error.
- */
-int ubigen_get_leb_total(ubi_info_t u, size_t* total);
-
-/**
- * @brief	  Get the size in bytes of one logical EB in the handle.
- * @param  u	  The handle.
- * @return 0	  On success.
- *	   else	  Error.
- */
-int ubigen_get_leb_size(ubi_info_t u, size_t* size);
-
-
-/**
- * @brief	  Write a logical EB (fits exactly into 1 physical EB).
- * @param  u	  Handle which holds all necessary data.
- * @param  action Additional operations which shall be applied on this
- *		  logical eraseblock. Mostly injecting artifical errors.
- * @return 0	  On success.
- *	   else	  Error.
- */
-int ubigen_write_leb(ubi_info_t u, ubigen_action_t action);
-
-/**
- * @brief	  Write a complete array of logical eraseblocks at once.
- * @param  u	  Handle which holds all necessary data.
- * @return 0	  On success.
- *	   else	  Error.
- */
-int ubigen_write_complete(ubi_info_t u);
-
-/**
- * @brief	  Write a single block which is extracted from the
- *		  binary input data.
- * @param  u	  Handle which holds all necessary data.
- * @param  blk	  Logical eraseblock which shall hold a inc. copy entry
- *		  and a bad data crc.
- * @return 0	  On success.
- *	   else	  Error.
- */
-int ubigen_write_broken_update(ubi_info_t u, uint32_t blk);
-
-/**
- * @brief	  Use the current ubi_info data and some additional data
- *		  to set an UBI volume table entry from it.
- * @param  u	  Handle which holds some of the necessary data.
- * @param  res_bytes Number of reserved bytes which is stored in the volume
- *		     table entry.
- * @param  name	   A string which shall be used as a volume label.
- * @param  lvol_r  A pointer to a volume table entry.
- * @return 0	   On success.
- *	   else	   Error.
- */
-int ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes,
-		const char* name, struct ubi_vtbl_record *lvol_rec);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __UBIGEN_H__ */
diff --git a/ubi-utils/src/ubimirror.c b/ubi-utils/src/ubimirror.c
deleted file mode 100644
index da05a8b..0000000
--- a/ubi-utils/src/ubimirror.c
+++ /dev/null
@@ -1,213 +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
- *
- * 1.2 Removed argp because we want to use uClibc.
- * 1.3 Minor cleanups
- * 1.4 Migrated to new libubi
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <errno.h>
-#include <mtd/ubi-media.h>
-
-#include "config.h"
-#include "error.h"
-#include "example_ubi.h"
-#include "ubimirror.h"
-
-#define PROGRAM_VERSION "1.4"
-
-typedef enum action_t {
-	ACT_NORMAL = 0,
-	ACT_ARGP_ABORT,
-	ACT_ARGP_ERR,
-} action_t;
-
-#define ABORT_ARGP do {			\
-	args->action = ACT_ARGP_ABORT;	\
-} while (0)
-
-#define ERR_ARGP do {			\
-	args->action = ACT_ARGP_ERR;	\
-} while (0)
-
-#define VOL_ARGS_MAX 2
-
-static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
-	"ubimirror - mirrors ubi volumes.\n";
-
-static const char *optionsstr =
-"  -c, --copyright            Print copyright information.\n"
-"  -s, --side=<seqnum>        Use the side <seqnum> as source.\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: ubimirror [-c?V] [-s <seqnum>] [--copyright] [--side=<seqnum>]\n"
-"            [--help] [--usage] [--version] <source> <destination>\n";
-
-static const char copyright [] __attribute__((unused)) =
-	"(C) IBM Coorporation 2007";
-
-struct option long_options[] = {
-	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
-	{ .name = "side", .has_arg = 1, .flag = NULL, .val = 's' },
-	{ .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}
-};
-
-typedef struct myargs {
-	action_t action;
-	int side;
-	int vol_no;			/* index of current volume */
-	/* @FIXME replace by bootenv_list, makes live easier */
-	/* @FIXME remove the constraint of two entries in the array */
-	const char* vol[VOL_ARGS_MAX];	/* comma separated list of src/dst
-					   volumes */
-	char *arg1;
-	char **options;		/* [STRING...] */
-} myargs;
-
-static int
-get_update_side(const char* str)
-{
-	uint32_t i = strtoul(str, NULL, 0);
-
-	if ((i != 0) && (i != 1)) {
-		return -1;
-	}
-	return i;
-}
-
-
-static int
-parse_opt(int argc, char **argv, myargs *args)
-{
-	while (1) {
-		int key;
-
-		key = getopt_long(argc, argv, "cs:?V", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-			case 'c':
-				err_msg("%s", copyright);
-				ABORT_ARGP;
-				break;
-			case 's':
-				args->side = get_update_side(optarg);
-				if (args->side < 0) {
-					err_msg("Unsupported seqnum: %s.\n"
-						"Supported seqnums are '0' "
-						"and '1'\n", optarg);
-					ERR_ARGP;
-				}
-				break;
-			case '?': /* help */
-				err_msg("Usage: ubimirror [OPTION...] "
-					"<source> <destination>\n");
-				err_msg("%s", doc);
-				err_msg("%s", optionsstr);
-				err_msg("\nReport bugs to %s\n",
-					PACKAGE_BUGREPORT);
-				exit(0);
-				break;
-			case 'V':
-				err_msg("%s", PROGRAM_VERSION);
-				exit(0);
-				break;
-			default:
-				err_msg("%s", usage);
-				exit(-1);
-			}
-	}
-
-	while (optind < argc) {
-		/* only two entries allowed */
-		if (args->vol_no >= VOL_ARGS_MAX) {
-			err_msg("%s", usage);
-			ERR_ARGP;
-		}
-		args->vol[(args->vol_no)++] = argv[optind++];
-	}
-
-	return 0;
-}
-
-
-int
-main(int argc, char **argv) {
-	int rc = 0;
-	unsigned int ids[VOL_ARGS_MAX];
-	char err_buf[1024];
-
-	myargs args = {
-		.action = ACT_NORMAL,
-		.side = -1,
-		.vol_no = 0,
-		.vol = {"", ""},
-		.options = NULL,
-	};
-
-	parse_opt(argc, argv, &args);
-	if (args.action == ACT_ARGP_ERR) {
-		rc = 127;
-		goto err;
-	}
-	if (args.action == ACT_ARGP_ABORT) {
-		rc = 126;
-		goto out;
-	}
-	if (args.vol_no < VOL_ARGS_MAX) {
-		fprintf(stderr, "missing volume number for %s\n",
-			args.vol_no == 0 ? "source and target" : "target");
-		rc = 125;
-		goto out;
-	}
-	for( rc = 0; rc < args.vol_no; ++rc){
-		char *endp;
-		ids[rc] = strtoul(args.vol[rc], &endp, 0);
-		if( *endp != '\0' ){
-			fprintf(stderr, "invalid volume number %s\n",
-					args.vol[rc]);
-			rc = 125;
-			goto out;
-		}
-	}
-	rc = ubimirror(EXAMPLE_UBI_DEVICE, args.side, ids, args.vol_no,
-		       err_buf, sizeof(err_buf));
-	if( rc ){
-		err_buf[sizeof err_buf - 1] = '\0';
-		fprintf(stderr, "%s", err_buf);
-		if( rc < 0 )
-			rc = -rc;
-	}
- out:
- err:
-	return rc;
-}
diff --git a/ubi-utils/src/ubimirror.h b/ubi-utils/src/ubimirror.h
deleted file mode 100644
index d7ae2ad..0000000
--- a/ubi-utils/src/ubimirror.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef __UBIMIRROR_H__
-#define __UBIMIRROR_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: Oliver Lohmann
- *
- * An utility to mirror UBI volumes.
- */
-
-#include <stdint.h>
-
-/**
- * @def EUBIMIRROR_SRC_EQ_DST
- *	@brief Given source volume is also in the set of destination volumes.
- */
-#define EUBIMIRROR_SRC_EQ_DST	20
-
-/**
- * @def EUBIMIRROR_NO_SRC
- *	@brief The given source volume does not exist.
- */
-#define EUBIMIRROR_NO_SRC	21
-
-/**
- * @def EUBIMIRROR_NO_DST
- *	@brief One of the given destination volumes does not exist.
- */
-#define EUBIMIRROR_NO_DST	22
-
-/**
- * @brief Mirrors UBI devices from a source device (specified by seqnum)
- *	  to n target devices.
- * @param devno Device number used by the UBI operations.
- * @param seqnum An index into ids (defines the src_id).
- * @param ids An array of ids.
- * @param ids_size The number of entries in the ids array.
- * @param err_buf A buffer to store verbose error messages.
- * @param err_buf_size The size of the error buffer.
- *
- * @note A seqnum of value < 0 defaults to a seqnum of 0.
- * @note A seqnum exceeding the range of ids_size defaults to 0.
- * @note An empty ids list results in a empty stmt.
- * @pre	The UBI volume which shall be used as source volume exists.
- * @pre	The UBI volumes which are defined as destination volumes exist.
- * @post The content of the UBI volume which was defined as source volume
- *	 equals the content of the volumes which were defined as destination.
- */
-int ubimirror(uint32_t devno, int seqnum, uint32_t* ids, ssize_t ids_size,
-	      char *err_buf, size_t err_buf_size);
-
-#endif /* __UBIMIRROR_H__ */
diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/src/ubimkvol.c
new file mode 100644
index 0000000..820c9d8
--- /dev/null
+++ b/ubi-utils/src/ubimkvol.c
@@ -0,0 +1,313 @@
+/*
+ * 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    "ubimkvol"
+
+/* 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;
+	const char *node;
+	int maxavs;
+	/* For deprecated -d option handling */
+	int devn;
+	char dev_name[256];
+};
+
+static struct args args = {
+	.vol_type = UBI_DYNAMIC_VOLUME,
+	.bytes = -1,
+	.lebs = -1,
+	.alignment = 1,
+	.vol_id = UBI_VOL_NUM_AUTO,
+	.devn = -1,
+};
+
+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\n\n"
+"The following is a compatibility option which is deprecated, do not use it\n"
+"-d, --devn=<devn>             UBI device number - may be used instead of the UBI\n"
+"                              device node name in which case the utility assumes\n"
+"                              that the device node is \"/dev/ubi<devn>\"";
+
+
+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' },
+	/* Deprecated -d option */
+	{ .name = "devn",      .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ 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:h?Vmd:", 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 'd':
+			/* Handle deprecated -d option */
+			warnmsg("-d is depricated and will be removed, do not use it");
+			args.devn = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.devn < 0)
+				return errmsg("bad UBI device number: " "\"%s\"", optarg);
+			break;
+
+		case 'N':
+			args.name = optarg;
+			break;
+
+		case 'h':
+		case '?':
+			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;
+		}
+	}
+
+	/* Handle deprecated -d option */
+	if (args.devn != -1) {
+		sprintf(args.dev_name, "/dev/ubi%d", args.devn);
+		args.node = args.dev_name;
+	} else {
+		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(1);
+	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 (dev_info.avail_bytes == 0) {
+		errmsg("UBI device does not have free logical eraseblocks");
+		goto out_libubi;
+	}
+
+	if (args.maxavs) {
+		args.bytes = dev_info.avail_bytes;
+		printf("Set volume size to %lld\n", args.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/ubinfo.c b/ubi-utils/src/ubinfo.c
new file mode 100644
index 0000000..536ec01
--- /dev/null
+++ b/ubi-utils/src/ubinfo.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2007, 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 version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to get UBI information.
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#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    "ubinfo"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int devn;
+	int vol_id;
+	int all;
+	const char *node;
+};
+
+static struct args args = {
+	.vol_id = -1,
+	.devn = -1,
+	.all = 0,
+	.node = NULL,
+};
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+			 " - a tool to print UBI information.";
+
+static const char *optionsstr =
+"-d, --devn=<UBI device number>  UBI device number to get information about\n"
+"-n, --vol_id=<volume ID>        ID of UBI volume to print information about\n"
+"-a, --all                       print information about all devices and volumes,\n"
+"                                or about all volumes if the UBI device was\n"
+"                                specified\n"
+"-h, --help                      print help message\n"
+"-V, --version                   print program version";
+
+static const char *usage =
+"Usage 1: " PROGRAM_NAME " [-d <UBI device number>] [-n <volume ID>] [-a] [-h] [-V] [--vol_id=<volume ID>]\n"
+"\t\t[--devn <UBI device number>] [--all] [--help] [--version]\n"
+"Usage 2: " PROGRAM_NAME " <UBI device node file name> [-a] [-h] [-V] [--all] [--help] [--version]\n"
+"Usage 3: " PROGRAM_NAME " <UBI volume node file name> [-h] [-V] [--help] [--version]\n\n"
+"Example 1: " PROGRAM_NAME " - (no arguments) print general UBI information\n"
+"Example 2: " PROGRAM_NAME " -d 1 - print information about UBI device number 1\n"
+"Example 3: " PROGRAM_NAME " /dev/ubi0 -a - print information about all volumes of UBI\n"
+"           device /dev/ubi0\n"
+"Example 4: " PROGRAM_NAME " /dev/ubi1_0 - print information about UBI volume /dev/ubi1_0\n"
+"Example 5: " PROGRAM_NAME " -a - print all information\n";
+
+static const struct option long_options[] = {
+	{ .name = "devn",      .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ .name = "vol_id",    .has_arg = 1, .flag = NULL, .val = 'n' },
+	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
+	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key;
+		char *endp;
+
+		key = getopt_long(argc, argv, "an:d:hV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'a':
+			args.all = 1;
+			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 'd':
+			args.devn = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.devn < 0)
+				return errmsg("bad UBI device number: \"%s\"", optarg);
+
+			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 ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc - 1)
+		args.node = argv[optind];
+	else if (optind < argc)
+		return errmsg("more then one UBI devices specified (use -h for help)");
+
+	return 0;
+}
+
+static int translate_dev(libubi_t libubi, const char *node)
+{
+	int err;
+
+	err = ubi_node_type(libubi, node);
+	if (err == -1) {
+		if (errno)
+			return errmsg("unrecognized device node \"%s\"", node);
+		return errmsg("\"%s\" does not correspond to any UBI device or volume", node);
+	}
+
+	if (err == 1) {
+		struct ubi_dev_info dev_info;
+
+		err = ubi_get_dev_info(libubi, node, &dev_info);
+		if (err)
+			return sys_errmsg("cannot get information about UBI device \"%s\"", node);
+
+		args.devn = dev_info.dev_num;
+	} else {
+		struct ubi_vol_info vol_info;
+
+		err = ubi_get_vol_info(libubi, node, &vol_info);
+		if (err)
+			return sys_errmsg("cannot get information about UBI volume \"%s\"", node);
+
+		if (args.vol_id != -1)
+			return errmsg("both volume character device node (\"%s\") and "
+				      "volume ID (%d) are specify, use only one of them"
+				      "(use -h for help)", node, args.vol_id);
+
+		args.devn = vol_info.dev_num;
+		args.vol_id = vol_info.vol_id;
+	}
+
+	return 0;
+}
+
+static int print_vol_info(libubi_t libubi, int dev_num, int vol_id)
+{
+	int err;
+	struct ubi_vol_info vol_info;
+
+	err = ubi_get_vol_info1(libubi, dev_num, vol_id, &vol_info);
+	if (err)
+		return sys_errmsg("cannot get information about UBI volume %d on ubi%d",
+				  vol_id, dev_num);
+
+	printf("Volume ID:   %d (on ubi%d)\n", vol_info.vol_id, vol_info.dev_num);
+	printf("Type:        %s\n",
+	       vol_info.type == UBI_DYNAMIC_VOLUME ?  "dynamic" : "static");
+	printf("Alignment:   %d\n", vol_info.alignment);
+
+	printf("Size:        %d LEBs (", vol_info.rsvd_lebs);
+	ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
+	printf(")\n");
+
+	if (vol_info.type == UBI_STATIC_VOLUME) {
+		printf("Data bytes:  ");
+		ubiutils_print_bytes(vol_info.data_bytes, 1);
+		printf("\n");
+	}
+	printf("State:       %s\n", vol_info.corrupted ? "corrupted" : "OK");
+	printf("Name:        %s\n", vol_info.name);
+	printf("Character device major/minor: %d:%d\n",
+	       vol_info.major, vol_info.minor);
+
+	return 0;
+}
+
+static int print_dev_info(libubi_t libubi, int dev_num, int all)
+{
+	int i, err, first = 1;
+	struct ubi_dev_info dev_info;
+	struct ubi_vol_info vol_info;
+
+	err = ubi_get_dev_info1(libubi, dev_num, &dev_info);
+	if (err)
+		return sys_errmsg("cannot get information about UBI device %d", dev_num);
+
+	printf("ubi%d:\n", dev_info.dev_num);
+	printf("Volumes count:                           %d\n", dev_info.vol_count);
+	printf("Logical eraseblock size:                 %d\n", dev_info.leb_size);
+
+	printf("Total amount of logical eraseblocks:     %d (", dev_info.total_lebs);
+	ubiutils_print_bytes(dev_info.total_bytes, 0);
+	printf(")\n");
+
+	printf("Amount of available logical eraseblocks: %d (", dev_info.avail_lebs);
+	ubiutils_print_bytes(dev_info.avail_bytes, 0);
+	printf(")\n");
+
+	printf("Maximum count of volumes                 %d\n", dev_info.max_vol_count);
+	printf("Count of bad physical eraseblocks:       %d\n", dev_info.bad_count);
+	printf("Count of reserved physical eraseblocks:  %d\n", dev_info.bad_rsvd);
+	printf("Current maximum erase counter value:     %lld\n", dev_info.max_ec);
+	printf("Minimum input/output unit size:          %d bytes\n", dev_info.min_io_size);
+	printf("Character device major/minor:            %d:%d\n",
+	       dev_info.major, dev_info.minor);
+
+	if (dev_info.vol_count == 0)
+		return 0;
+
+	printf("Present volumes:                         ");
+	for (i = dev_info.lowest_vol_id;
+	     i <= dev_info.highest_vol_id; i++) {
+		err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+
+			return sys_errmsg("libubi failed to probe volume %d on ubi%d",
+					  i, dev_info.dev_num);
+		}
+
+		if (!first)
+			printf(", %d", i);
+		else {
+			printf("%d", i);
+			first = 0;
+		}
+	}
+	printf("\n");
+
+	if (!all)
+		return 0;
+
+	first = 1;
+	printf("\n");
+
+	for (i = dev_info.lowest_vol_id;
+	     i <= dev_info.highest_vol_id; i++) {
+		if(!first)
+			printf("-----------------------------------\n");
+		err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+
+			return sys_errmsg("libubi failed to probe volume %d on ubi%d",
+					  i, dev_info.dev_num);
+		}
+		first = 0;
+
+		err = print_vol_info(libubi, dev_info.dev_num, i);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int print_general_info(libubi_t libubi, int all)
+{
+	int i, err, first = 1;
+	struct ubi_info ubi_info;
+	struct ubi_dev_info dev_info;
+
+	err = ubi_get_info(libubi, &ubi_info);
+	if (err)
+		return sys_errmsg("cannot get UBI information");
+
+	printf("UBI version:                    %d\n", ubi_info.version);
+	printf("Count of UBI devices:           %d\n", ubi_info.dev_count);
+	if (ubi_info.ctrl_major != -1)
+		printf("UBI control device major/minor: %d:%d\n",
+		       ubi_info.ctrl_major, ubi_info.ctrl_minor);
+	else
+		printf("UBI control device is not supported by this kernel\n");
+
+	if (ubi_info.dev_count == 0)
+		return 0;
+
+	printf("Present UBI devices:            ");
+	for (i = ubi_info.lowest_dev_num;
+	     i <= ubi_info.highest_dev_num; i++) {
+		err = ubi_get_dev_info1(libubi, i, &dev_info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+
+			return sys_errmsg("libubi failed to probe UBI device %d", i);
+		}
+
+		if (!first)
+			printf(", ubi%d", i);
+		else {
+			printf("ubi%d", i);
+			first = 0;
+		}
+	}
+	printf("\n");
+
+	if (!all)
+		return 0;
+
+	first = 1;
+	printf("\n");
+
+	for (i = ubi_info.lowest_dev_num;
+	     i <= ubi_info.highest_dev_num; i++) {
+		if(!first)
+			printf("\n===================================\n\n");
+		err = ubi_get_dev_info1(libubi, i, &dev_info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+
+			return sys_errmsg("libubi failed to probe UBI device %d", i);
+		}
+		first = 0;
+
+		err = print_dev_info(libubi, i, all);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	if (!args.node && args.devn != -1)
+		return errmsg("specify either device number or node file (use -h for help)");
+
+	libubi = libubi_open(1);
+	if (libubi == NULL)
+		return sys_errmsg("cannot open libubi");
+
+	if (args.node) {
+		/*
+		 * A character device was specified, translate this into UBI
+		 * device number and volume ID.
+		 */
+		err = translate_dev(libubi, args.node);
+		if (err)
+			goto out_libubi;
+	}
+
+	if (args.vol_id != -1 && args.devn == -1) {
+		errmsg("volume ID is specified, but UBI device number is not "
+		       "(use -h for help)\n");
+		goto out_libubi;
+	}
+
+	if (args.devn != -1 && args.vol_id != -1) {
+		print_vol_info(libubi, args.devn, args.vol_id);
+		goto out;
+	}
+
+	if (args.devn == -1 && args.vol_id == -1)
+		err = print_general_info(libubi, args.all);
+	else if (args.devn != -1 && args.vol_id == -1)
+		err = print_dev_info(libubi, args.devn, args.all);
+
+	if (err)
+		goto out_libubi;
+
+out:
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/src/ubinize.c b/ubi-utils/src/ubinize.c
new file mode 100644
index 0000000..0762aa8
--- /dev/null
+++ b/ubi-utils/src/ubinize.c
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation
+ * 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.
+ */
+
+/*
+ * Generate UBI images.
+ *
+ * Authors: Artem Bityutskiy
+ *          Oliver Lohmann
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <mtd/ubi-media.h>
+#include <libubigen.h>
+#include <libiniparser.h>
+#include "common.h"
+
+#define PROGRAM_VERSION "1.1"
+#define PROGRAM_NAME    "ubinize"
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+" - a tool to generate UBI images. An UBI image may contain one or more UBI "
+"volumes which have to be defined in the input configuration ini-file. The "
+"ini file defines all the UBI volumes - their characteristics and the and the "
+"contents, but it does not define the characteristics of the flash the UBI "
+"image is generated for. Instead, the flash characteristics are defined via "
+"the command-line options. Note, if not sure about some of the command-line "
+"parameters, do not specify them and let the utility to use default values.";
+
+static const char *optionsstr =
+"-o, --output=<file name>     output file name\n"
+"-p, --peb-size=<bytes>       size of the physical eraseblock of the flash\n"
+"                             this UBI image is created for in bytes,\n"
+"                             kilobytes (KiB), or megabytes (MiB)\n"
+"                             (mandatory parameter)\n"
+"-m, --min-io-size=<bytes>    minimum input/output unit size of the flash\n"
+"                             in bytes\n"
+"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
+"                             headers, e.g. sub-page size in case of NAND\n"
+"                             flash (equivalent to the minimum input/output\n"
+"                             unit size by default)\n"
+"-O, --vid-hdr-offset=<num>   offset if the VID header from start of the\n"
+"                             physical eraseblock (default is the next\n"
+"                             minimum I/O unit or sub-page after the EC\n"
+"                             header)\n"
+"-e, --erase-counter=<num>    the erase counter value to put to EC headers\n"
+"                             (default is 0)\n"
+"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
+"                             (default is 1)\n"
+"-v, --verbose                be verbose\n"
+"-h, --help                   print help message\n"
+"-V, --version                print program version";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME " [-o filename] [-h] [-V] [--output=<filename>] [--help]\n"
+"\t\t[--version] ini-file\n"
+"Example: " PROGRAM_NAME " -o ubi.img -p 16KiB -m 512 -s 256 cfg.ini - create UBI image\n"
+"         'ubi.img' as described by configuration file 'cfg.ini'";
+
+static const char *ini_doc = "INI-file format.\n"
+"The input configuration ini-file describes all the volumes which have to\n"
+"be included to the output UBI image. Each volume is described in its own\n"
+"section which may be named arbitrarily. The section consists on\n"
+"\"key=value\" pairs, for example:\n\n"
+"[jffs2-volume]\n"
+"mode=ubi\n"
+"image=../jffs2.img\n"
+"vol_id=1\n"
+"vol_size=30MiB\n"
+"vol_type=dynamic\n"
+"vol_name=jffs2_volume\n"
+"vol_flags=autoresize\n"
+"vol_alignment=1\n\n"
+"This example configuration file tells the utility to create an UBI image\n"
+"with one volume with ID 1, volume size 30MiB, the volume is dynamic, has\n"
+"name \"jffs2_volume\", \"autoresize\" volume flag, and alignment 1. The\n"
+"\"image=../jffs2.img\" line tells the utility to take the contents of the\n"
+"volume from the \"../jffs2.img\" file. The size of the image file has to be\n"
+"less or equivalent to the volume size (30MiB). The \"mode=ubi\" line is\n"
+"mandatory and just tells that the section describes an UBI volume - other\n"
+"section modes may be added in the future.\n"
+"Notes:\n"
+"  * size in vol_size might be specified kilobytes (KiB), megabytes (MiB),\n"
+"    gigabytes (GiB) or bytes (no modifier);\n"
+"  * if \"vol_size\" key is absent, the volume size is assumed to be\n"
+"    equivalent to the size of the image file (defined by \"image\" key);\n"
+"  * if the \"image\" is absent, the volume is assumed to be empty;\n"
+"  * volume alignment must not be greater than the logical eraseblock size;\n"
+"  * one ini file may contain arbitrary number of sections, the utility will\n"
+"    put all the volumes which are described by these section to the output\n"
+"    UBI image file.";
+
+struct option long_options[] = {
+	{ .name = "output",         .has_arg = 1, .flag = NULL, .val = 'o' },
+	{ .name = "peb-size",       .has_arg = 1, .flag = NULL, .val = 'p' },
+	{ .name = "min-io-size",    .has_arg = 1, .flag = NULL, .val = 'm' },
+	{ .name = "sub-page-size",  .has_arg = 1, .flag = NULL, .val = 's' },
+	{ .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
+	{ .name = "erase-counter",  .has_arg = 1, .flag = NULL, .val = 'e' },
+	{ .name = "ubi-ver",        .has_arg = 1, .flag = NULL, .val = 'x' },
+	{ .name = "verbose",        .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0}
+};
+
+struct args {
+	const char *f_in;
+	const char *f_out;
+	int out_fd;
+	int peb_size;
+	int min_io_size;
+	int subpage_size;
+	int vid_hdr_offs;
+	int ec;
+	int ubi_ver;
+	int verbose;
+	dictionary *dict;
+};
+
+static struct args args = {
+	.peb_size     = -1,
+	.min_io_size  = -1,
+	.subpage_size = -1,
+	.ubi_ver      = 1,
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key;
+		char *endp;
+
+		key = getopt_long(argc, argv, "o:p:m:s:O:e:x:vhV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'o':
+			args.out_fd = open(optarg, O_CREAT | O_TRUNC | O_WRONLY,
+					   S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP | S_IROTH);
+			if (args.out_fd == -1)
+				return sys_errmsg("cannot open file \"%s\"", optarg);
+			args.f_out = optarg;
+			break;
+
+		case 'p':
+			args.peb_size = ubiutils_get_bytes(optarg);
+			if (args.peb_size <= 0)
+				return errmsg("bad physical eraseblock size: \"%s\"", optarg);
+			break;
+
+		case 'm':
+			args.min_io_size = ubiutils_get_bytes(optarg);
+			if (args.min_io_size <= 0)
+				return errmsg("bad min. I/O unit size: \"%s\"", optarg);
+			if (!is_power_of_2(args.min_io_size))
+				return errmsg("min. I/O unit size should be power of 2");
+			break;
+
+		case 's':
+			args.subpage_size = ubiutils_get_bytes(optarg);
+			if (args.subpage_size <= 0)
+				return errmsg("bad sub-page size: \"%s\"", optarg);
+			if (!is_power_of_2(args.subpage_size))
+				return errmsg("sub-page size should be power of 2");
+			break;
+
+		case 'O':
+			args.vid_hdr_offs = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.vid_hdr_offs < 0)
+				return errmsg("bad VID header offset: \"%s\"", optarg);
+			break;
+
+		case 'e':
+			args.ec = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.ec < 0)
+				return errmsg("bad erase counter value: \"%s\"", optarg);
+			break;
+
+		case 'x':
+			args.ubi_ver = strtoul(optarg, &endp, 0);
+			if (*endp != '\0'  || endp == optarg || args.ubi_ver < 0)
+				return errmsg("bad UBI version: \"%s\"", optarg);
+			break;
+
+		case 'v':
+			args.verbose = 1;
+			break;
+
+		case 'h':
+			ubiutils_print_text(stderr, doc, 80);
+			fprintf(stderr, "\n%s\n\n", ini_doc);
+			fprintf(stderr, "%s\n", usage);
+			fprintf(stderr, "%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc)
+		return errmsg("input configuration file was not specified (use -h for help)");
+
+	if (optind != argc - 1)
+		return errmsg("more then one configuration file was specified (use -h for help)");
+
+	args.f_in = argv[optind];
+
+	if (args.peb_size < 0)
+		return errmsg("physical eraseblock size was not specified (use -h for help)");
+
+	if (args.peb_size > 1024*1024)
+		return errmsg("too high physical eraseblock size %d", args.peb_size);
+
+	if (args.min_io_size < 0)
+		return errmsg("min. I/O unit size was not specified (use -h for help)");
+
+	if (args.subpage_size < 0)
+		args.subpage_size = args.min_io_size;
+
+	if (args.subpage_size > args.min_io_size)
+		return errmsg("sub-page cannot be larger then min. I/O unit");
+
+	if (args.peb_size % args.min_io_size)
+		return errmsg("physical eraseblock should be multiple of min. I/O units");
+
+	if (args.min_io_size % args.subpage_size)
+		return errmsg("min. I/O unit size should be multiple of sub-page size");
+
+	if (!args.f_out)
+		return errmsg("output file was not specified (use -h for help)");
+
+	if (args.vid_hdr_offs) {
+		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE >= args.peb_size)
+			return errmsg("bad VID header position");
+		if (args.vid_hdr_offs % 8)
+			return errmsg("VID header offset has to be multiple of min. I/O unit size");
+	}
+
+	return 0;
+}
+
+static int read_section(const struct ubigen_info *ui, const char *sname,
+			struct ubigen_vol_info *vi, const char **img,
+			struct stat *st)
+{
+	char buf[256];
+	const char *p;
+
+	*img = NULL;
+
+	if (strlen(sname) > 128)
+		return errmsg("too long section name \"%s\"", sname);
+
+	/* Make sure mode is UBI, otherwise ignore this section */
+	sprintf(buf, "%s:mode", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (!p) {
+		errmsg("\"mode\" key not found in section \"%s\"", sname);
+		errmsg("the \"mode\" key is mandatory and has to be "
+		       "\"mode=ubi\" if the section describes an UBI volume");
+		return -1;
+	}
+
+	/* If mode is not UBI, skip this section */
+	if (strcmp(p, "ubi")) {
+		verbose(args.verbose, "skip non-ubi section \"%s\"", sname);
+		return 1;
+	}
+
+	verbose(args.verbose, "mode=ubi, keep parsing");
+
+	/* Fetch volume type */
+	sprintf(buf, "%s:vol_type", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (!p) {
+		normsg("volume type was not specified in "
+		       "section \"%s\", assume \"dynamic\"\n", sname);
+		vi->type = UBI_VID_DYNAMIC;
+	} else {
+		if (!strcmp(p, "static"))
+			vi->type = UBI_VID_STATIC;
+		else if (!strcmp(p, "dynamic"))
+			vi->type = UBI_VID_DYNAMIC;
+		else
+			return errmsg("invalid volume type \"%s\" in section  \"%s\"",
+				      p, sname);
+	}
+
+	verbose(args.verbose, "volume type: %s",
+		vi->type == UBI_VID_DYNAMIC ? "dynamic" : "static");
+
+	/* Fetch the name of the volume image file */
+	sprintf(buf, "%s:image", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (p) {
+		*img = p;
+		if (stat(p, st))
+			return sys_errmsg("cannot stat \"%s\" referred from section \"%s\"",
+					  p, sname);
+		if (st->st_size == 0)
+			return errmsg("empty file \"%s\" referred from section \"%s\"",
+				       p, sname);
+	} else if (vi->type == UBI_VID_STATIC)
+		return errmsg("image is not specified for static volume in section \"%s\"",
+			      sname);
+
+	/* Fetch volume id */
+	sprintf(buf, "%s:vol_id", sname);
+	vi->id = iniparser_getint(args.dict, buf, -1);
+	if (vi->id == -1)
+		return errmsg("\"vol_id\" key not found in section  \"%s\"", sname);
+	if (vi->id < 0)
+		return errmsg("negative volume ID %d in section \"%s\"",
+			      vi->id, sname);
+	if (vi->id >= ui->max_volumes)
+		return errmsg("too high volume ID %d in section \"%s\", max. is %d",
+			      vi->id, sname, ui->max_volumes);
+
+	verbose(args.verbose, "volume ID: %d", vi->id);
+
+	/* Fetch volume size */
+	sprintf(buf, "%s:vol_size", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (p) {
+		vi->bytes = ubiutils_get_bytes(p);
+		if (vi->bytes <= 0)
+			return errmsg("bad \"vol_size\" key value \"%s\" (section \"%s\")",
+				      p, sname);
+
+		/* Make sure the image size is not larger than volume size */
+		if (*img && st->st_size > vi->bytes)
+			return errmsg("error in section \"%s\": size of the image file "
+				      "\"%s\" is %lld, which is larger than volume size %lld",
+				      sname, *img, (long long)st->st_size, vi->bytes);
+		verbose(args.verbose, "volume size: %lld bytes", vi->bytes);
+	} else {
+		struct stat st;
+
+		if (!*img)
+			return errmsg("neither image file (\"image=\") nor volume size "
+				      "(\"vol_size=\") specified in section \"%s\"", sname);
+
+		if (stat(*img, &st))
+			return sys_errmsg("cannot stat \"%s\"", *img);
+
+		vi->bytes = st.st_size;
+
+		if (vi->bytes == 0)
+			return errmsg("file \"%s\" referred from section \"%s\" is empty",
+				      *img, sname);
+
+		normsg_cont("volume size was not specified in section \"%s\", assume"
+			    " minimum to fit image \"%s\"", sname, *img);
+		ubiutils_print_bytes(vi->bytes, 1);
+		printf("\n");
+	}
+
+	/* Fetch volume name */
+	sprintf(buf, "%s:vol_name", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (!p)
+		return errmsg("\"vol_name\" key not found in section \"%s\"", sname);
+
+	vi->name = p;
+	vi->name_len = strlen(p);
+	if (vi->name_len > UBI_VOL_NAME_MAX)
+		return errmsg("too long volume name in section \"%s\", max. is %d characters",
+			      vi->name, UBI_VOL_NAME_MAX);
+
+	verbose(args.verbose, "volume name: %s", p);
+
+	/* Fetch volume alignment */
+	sprintf(buf, "%s:vol_alignment", sname);
+	vi->alignment = iniparser_getint(args.dict, buf, -1);
+	if (vi->alignment == -1)
+		vi->alignment = 1;
+	else if (vi->id < 0)
+		return errmsg("negative volume alignement %d in section \"%s\"",
+			      vi->alignment, sname);
+
+	verbose(args.verbose, "volume alignment: %d", vi->alignment);
+
+	/* Fetch volume flags */
+	sprintf(buf, "%s:vol_flags", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (p) {
+		if (!strcmp(p, "autoresize")) {
+			verbose(args.verbose, "autoresize flags found");
+			vi->flags |= UBI_VTBL_AUTORESIZE_FLG;
+		} else {
+			return errmsg("unknown flags \"%s\" in section \"%s\"",
+				      p, sname);
+		}
+	}
+
+	/* Initialize the rest of the volume information */
+	vi->data_pad = ui->leb_size % vi->alignment;
+	vi->usable_leb_size = ui->leb_size - vi->data_pad;
+	if (vi->type == UBI_VID_DYNAMIC)
+		vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size;
+	else
+		vi->used_ebs = (st->st_size + vi->usable_leb_size - 1) / vi->usable_leb_size;
+	vi->compat = 0;
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err = -1, sects, i, autoresize_was_already = 0;
+	struct ubigen_info ui;
+	struct ubi_vtbl_record *vtbl;
+	struct ubigen_vol_info *vi;
+	off_t seek;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	ubigen_info_init(&ui, args.peb_size, args.min_io_size,
+			 args.subpage_size, args.vid_hdr_offs,
+			 args.ubi_ver);
+
+	verbose(args.verbose, "LEB size:      %d", ui.leb_size);
+	verbose(args.verbose, "PEB size:      %d", ui.peb_size);
+	verbose(args.verbose, "min. I/O size: %d", ui.min_io_size);
+	verbose(args.verbose, "sub-page size: %d", args.subpage_size);
+	verbose(args.verbose, "VID offset:    %d", ui.vid_hdr_offs);
+	verbose(args.verbose, "data offset:   %d", ui.data_offs);
+
+	vtbl = ubigen_create_empty_vtbl(&ui);
+	if (!vtbl)
+		goto out;
+
+	args.dict = iniparser_load(args.f_in);
+	if (!args.dict) {
+		errmsg("cannot load the input ini file \"%s\"", args.f_in);
+		goto out_vtbl;
+	}
+
+	verbose(args.verbose, "loaded the ini-file \"%s\"", args.f_in);
+
+	/* Each section describes one volume */
+	sects = iniparser_getnsec(args.dict);
+	if (sects == -1) {
+		errmsg("ini-file parsing error (iniparser_getnsec)");
+		goto out_dict;
+	}
+
+	verbose(args.verbose, "count of sections: %d", sects);
+	if (sects == 0) {
+		errmsg("no sections found the ini-file \"%s\"", args.f_in);
+		goto out_dict;
+	}
+
+	if (sects > ui.max_volumes) {
+		errmsg("too many sections (%d) in the ini-file \"%s\"",
+		       sects, args.f_in);
+		normsg("each section corresponds to an UBI volume, maximum "
+		       "count of volumes is %d", ui.max_volumes);
+		goto out_dict;
+	}
+
+	vi = calloc(sizeof(struct ubigen_vol_info), sects);
+	if (!vi) {
+		errmsg("cannot allocate memory");
+		goto out_dict;
+	}
+
+	/*
+	 * Skip 2 PEBs at the beginning of the file for the volume table which
+	 * will be written later.
+	 */
+	seek = ui.peb_size * 2;
+	if (lseek(args.out_fd, seek, SEEK_SET) != seek) {
+		sys_errmsg("cannot seek file \"%s\"", args.f_out);
+		goto out_free;
+	}
+
+	for (i = 0; i < sects; i++) {
+		const char *sname = iniparser_getsecname(args.dict, i);
+		const char *img = NULL;
+		struct stat st;
+		int fd, j;
+
+		if (!sname) {
+			errmsg("ini-file parsing error (iniparser_getsecname)");
+			goto out_free;
+		}
+
+		if (args.verbose)
+			printf("\n");
+		verbose(args.verbose, "parsing section \"%s\"", sname);
+
+		err = read_section(&ui, sname, &vi[i], &img, &st);
+		if (err == -1)
+			goto out_free;
+
+		verbose(args.verbose, "adding volume %d", vi[i].id);
+
+		/*
+		 * Make sure that volume ID and name is unique and that only
+		 * one volume has auto-resize flag
+		 */
+		for (j = 0; j < i; j++) {
+			if (vi[i].id == vi[j].id) {
+				errmsg("volume IDs must be unique, but ID %d "
+				       "in section \"%s\" is not",
+				       vi[i].id, sname);
+				goto out_free;
+			}
+
+			if (!strcmp(vi[i].name, vi[j].name)) {
+				errmsg("volume name must be unique, but name "
+				       "\"%s\" in section \"%s\" is not",
+				       vi[i].name, sname);
+				goto out_free;
+			}
+		}
+
+		if (vi[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
+			if (autoresize_was_already)
+				return errmsg("only one volume is allowed "
+					      "to have auto-resize flag");
+			autoresize_was_already = 1;
+		}
+
+		err = ubigen_add_volume(&ui, &vi[i], vtbl);
+		if (err) {
+			errmsg("cannot add volume for section \"%s\"", sname);
+			goto out_free;
+		}
+
+		if (img) {
+			fd = open(img, O_RDONLY);
+			if (fd == -1) {
+				sys_errmsg("cannot open \"%s\"", img);
+				goto out_free;
+			}
+
+			verbose(args.verbose, "writing volume %d", vi[i].id);
+			verbose(args.verbose, "image file: %s", img);
+
+			err = ubigen_write_volume(&ui, &vi[i], args.ec, st.st_size, fd, args.out_fd);
+			close(fd);
+			if (err) {
+				errmsg("cannot write volume for section \"%s\"", sname);
+				goto out_free;
+			}
+		}
+
+		if (args.verbose)
+			printf("\n");
+	}
+
+	verbose(args.verbose, "writing layout volume");
+
+	err = ubigen_write_layout_vol(&ui, 0, 1, args.ec, args.ec, vtbl, args.out_fd);
+	if (err) {
+		errmsg("cannot write layout volume");
+		goto out_free;
+	}
+
+	verbose(args.verbose, "done");
+
+	free(vi);
+	iniparser_freedict(args.dict);
+	free(vtbl);
+	close(args.out_fd);
+	return 0;
+
+out_free:
+	free(vi);
+out_dict:
+	iniparser_freedict(args.dict);
+out_vtbl:
+	free(vtbl);
+out:
+	close(args.out_fd);
+	remove(args.f_out);
+	return err;
+}
diff --git a/ubi-utils/src/ubirename.c b/ubi-utils/src/ubirename.c
new file mode 100644
index 0000000..8f33718
--- /dev/null
+++ b/ubi-utils/src/ubirename.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2008 Logitech.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to get rename UBI volumes.
+ *
+ * Author: Richard Titmuss
+ */
+
+#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    "ubirename"
+
+static const char *usage =
+"Usage: " PROGRAM_NAME " <UBI device node file name> [<old name> <new name>|...]\n\n"
+"Example: " PROGRAM_NAME "/dev/ubi0 A B C D - rename volume A to B, and C to D\n\n"
+"This utility allows re-naming several volumes in one go atomically.\n"
+"For example, if you have volumes A and B, then you may rename A into B\n"
+"and B into A at one go, and the operation will be atomic. This allows\n"
+"implementing atomic UBI volumes upgrades. E.g., if you have volume A\n"
+"and want to upgrade it atomically, you create a temporary volume B,\n"
+"put your new data to B, then rename A to B and B to A, and then you\n"
+"may remove old volume B.\n"
+"It is also allowed to re-name multiple volumes at a time, but 16 max.\n"
+"renames at once, which means you may specify up to 32 volume names.\n"
+"If you have volumes A and B, and re-name A to B, bud do not re-name\n"
+"B to something else in the same request, old volume B will be removed\n"
+"and A will be renamed into B.\n";
+
+static int get_vol_id(libubi_t libubi, struct ubi_dev_info *dev_info,
+		       char *name)
+{
+	int err, i;
+	struct ubi_vol_info vol_info;
+
+	for (i=dev_info->lowest_vol_id; i<=dev_info->highest_vol_id; i++) {
+		err = ubi_get_vol_info1(libubi, dev_info->dev_num, i, &vol_info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+			return -1;
+		}
+
+		if (strcmp(name, vol_info.name) == 0)
+			return vol_info.vol_id;
+	}
+
+	return -1;
+}
+
+int main(int argc, char * const argv[])
+{
+	int i, err;
+	int count = 0;
+	libubi_t libubi;
+	struct ubi_dev_info dev_info;
+	struct ubi_rnvol_req rnvol;
+	const char *node;
+
+	if (argc < 3 || (argc & 1) == 1) {
+		errmsg("too few arguments");
+		fprintf(stderr, "%s\n", usage);
+		return -1;
+	}
+
+	if (argc > UBI_MAX_RNVOL + 2) {
+		errmsg("too many volumes to re-name, max. is %d",
+		       UBI_MAX_RNVOL);
+		return -1;
+	}
+
+	node = argv[1];
+	libubi = libubi_open(1);
+	if (!libubi)
+		return sys_errmsg("cannot open libubi");
+
+	err = ubi_node_type(libubi, node);
+	if (err == 2) {
+		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
+		       node);
+		goto out_libubi;
+	} else if (err < 0) {
+		errmsg("\"%s\" is not an UBI device node", node);
+		goto out_libubi;
+	}
+
+	err = ubi_get_dev_info(libubi, node, &dev_info);
+	if (err == -1) {
+		sys_errmsg("cannot get information about UBI device \"%s\"", node);
+		goto out_libubi;
+	}
+
+	for (i = 2; i < argc; i += 2) {
+		err = get_vol_id(libubi, &dev_info, argv[i]);
+		if (err == -1) {
+			errmsg("\"%s\" volume not found", argv[i]);
+			goto out_libubi;
+		}
+
+		rnvol.ents[count].vol_id = err;
+		rnvol.ents[count].name_len = strlen(argv[i + 1]);
+		strcpy(rnvol.ents[count++].name, argv[i + 1]);
+	}
+
+	rnvol.count = count;
+
+	err = ubi_rnvols(libubi, node, &rnvol);
+	if (err == -1) {
+		sys_errmsg("cannot rename volumes");
+		goto out_libubi;
+	}
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/src/ubirmvol.c
new file mode 100644
index 0000000..a4cf1df
--- /dev/null
+++ b/ubi-utils/src/ubirmvol.c
@@ -0,0 +1,230 @@
+/*
+ * 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    "ubirmvol"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int vol_id;
+	const char *node;
+	const char *name;
+	/* For deprecated -d option handling */
+	int devn;
+	char dev_name[256];
+};
+
+static struct args args = {
+	.vol_id = -1,
+	.devn = -1,
+};
+
+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"
+"-N, --name=<volume name>   volume name to remove\n"
+"-h, -?, --help             print help message\n"
+"-V, --version              print program version\n\n"
+"The following is a compatibility option which is deprecated, do not use it\n"
+"-d, --devn=<devn>          UBI device number - may be used instead of the UBI\n"
+"                           device node name in which case the utility assumes\n"
+"                           that the device node is \"/dev/ubi<devn>\"";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>]\n\n"
+"         [-N <volume name>] [--name=<volume name>] [-h] [--help]\n\n"
+"Example: " PROGRAM_NAME "/dev/ubi0 -n 1 - remove UBI volume 1 from UBI device corresponding\n"
+"         to /dev/ubi0\n"
+"         " PROGRAM_NAME "/dev/ubi0 -N my_vol - remove UBI named \"my_vol\" from UBI device\n"
+"         corresponding to /dev/ubi0";
+
+static const struct option long_options[] = {
+	{ .name = "vol_id",  .has_arg = 1, .flag = NULL, .val = 'n' },
+	{ .name = "name",    .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' },
+	/* Deprecated -d option */
+	{ .name = "devn",    .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int param_sanity_check(void)
+{
+	if (args.vol_id == -1 && !args.name) {
+		errmsg("please, specify either volume ID or volume name");
+		return -1;
+	}
+
+	if (args.vol_id != -1 && args.name) {
+		errmsg("please, specify either volume ID or volume name, not both");
+		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:N:h?Vd:", 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 'N':
+			args.name = optarg;
+			break;
+
+		case 'h':
+		case '?':
+			fprintf(stderr, "%s\n\n", doc);
+			fprintf(stderr, "%s\n\n", usage);
+			fprintf(stderr, "%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'd':
+			/* Handle deprecated -d option */
+			warnmsg("-d is depricated and will be removed, do not use it");
+			args.devn = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.devn < 0)
+				return errmsg("bad UBI device number: " "\"%s\"", optarg);
+			break;
+
+		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;
+		}
+	}
+
+	/* Handle deprecated -d option */
+	if (args.devn != -1) {
+		sprintf(args.dev_name, "/dev/ubi%d", args.devn);
+		args.node = args.dev_name;
+	} else {
+		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(1);
+	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;
+	}
+
+	if (args.name) {
+		struct ubi_dev_info dev_info;
+		struct ubi_vol_info vol_info;
+
+		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;
+		}
+
+		err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num,
+					   args.name, &vol_info);
+		if (err) {
+			sys_errmsg("cannot find UBI volume \"%s\"", args.name);
+			goto out_libubi;
+		}
+
+		args.vol_id = vol_info.vol_id;
+	}
+
+	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/ubiupdatevol.c b/ubi-utils/src/ubiupdatevol.c
new file mode 100644
index 0000000..c83731c
--- /dev/null
+++ b/ubi-utils/src/ubiupdatevol.c
@@ -0,0 +1,355 @@
+/*
+ * 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 <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.1"
+#define PROGRAM_NAME    "ubiupdatevol"
+
+struct args {
+	int truncate;
+	const char *node;
+	const char *img;
+	/* For deprecated -d and -B options handling */
+	int devn;
+	char dev_name[256];
+	int broken_update;
+	int size;
+	int use_stdin;
+};
+
+static struct args args = {
+	.devn = -1,
+};
+
+static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
+			 " - a tool to write data to UBI volumes.";
+
+static const char *optionsstr =
+"-t, --truncate             truncate volume (wipe it out)\n"
+"-h, --help                 print help message\n"
+"-V, --version              print program version\n\n"
+"-s, --size=<bytes>         bytes in input, if not reading from file\n"
+"The following are compatibility options which are deprecated, do not use them\n"
+"-d, --devn=<devn>          UBI device number - may be used instead of the UBI\n"
+"                           device node name in which case the utility assumes\n"
+"                           that the device node is \"/dev/ubi<devn>\"\n"
+"-B, --broken-update        broken update, this is for testing";
+
+static const char *usage =
+"Usage: " PROGRAM_NAME " <UBI volume node file name> [-t] [-h] [-V] [--truncate] [--size=x] [--help]\n"
+"\t\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' },
+	{ .name = "size",     .has_arg = 1, .flag = NULL, .val = 's' },
+	/* Deprecated -d and -B options */
+	{ .name = "devn",     .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ .name = "broken-update", .has_arg = 1, .flag = NULL, .val = 'B' },
+	{ NULL, 0, NULL, 0}
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key;
+		char *endp;
+
+		key = getopt_long(argc, argv, "n:th?Vd:s:", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 't':
+			args.truncate = 1;
+			break;
+
+		case 's':
+			args.size = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.size < 0)
+				return errmsg("bad size: " "\"%s\"", optarg);
+			break;
+
+		case 'h':
+		case '?':
+			fprintf(stderr, "%s\n\n", doc);
+			fprintf(stderr, "%s\n\n", usage);
+			fprintf(stderr, "%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'd':
+			/* Handle deprecated -d option */
+			warnmsg("-d is depricated and will be removed, do not use it");
+			args.devn = strtoul(optarg, &endp, 0);
+			if (*endp != '\0' || endp == optarg || args.devn < 0)
+				return errmsg("bad UBI device number: " "\"%s\"", optarg);
+			break;
+
+		case 'B':
+			/* Handle deprecated -B option */
+			warnmsg("-B is depricated and will be removed, do not use it");
+			args.broken_update = 1;
+			break;
+
+		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;
+		}
+	}
+
+	/* Handle deprecated -d option */
+	if (args.devn != -1) {
+		sprintf(args.dev_name, "/dev/ubi%d", args.devn);
+		args.node = args.dev_name;
+	} else {
+		if (optind == argc)
+			return errmsg("UBI device name was not specified (use -h for help)");
+		else if (optind != argc - 2 && !args.truncate)
+			return errmsg("specify UBI device name and image file name as first 2 "
+				      "parameters (use -h for help)");
+	}
+
+	args.node = argv[optind];
+	args.img  = argv[optind + 1];
+
+	if (args.img && args.truncate)
+		return errmsg("You can't truncate and specify an image (use -h for help)");
+
+	if (args.img && !args.truncate) {
+		if (strcmp(args.img, "-") == 0)
+			args.use_stdin = 1;
+		if (args.use_stdin && !args.size)
+			return errmsg("file size must be specified if input is stdin");
+	}
+
+	return 0;
+}
+
+static int truncate_volume(libubi_t libubi)
+{
+	int err, fd;
+
+	fd = open(args.node, O_RDWR);
+	if (fd == -1)
+		return sys_errmsg("cannot open \"%s\"", args.node);
+
+	err = ubi_update_start(libubi, fd, 0);
+	if (err) {
+		sys_errmsg("cannot truncate volume \"%s\"", args.node);
+		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;
+			}
+			return sys_errmsg("cannot write %d bytes to volume \"%s\"",
+					  len, args.node);
+		}
+
+		if (ret == 0)
+			return errmsg("cannot write %d bytes to volume \"%s\"", len, args.node);
+
+		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;
+	char *buf;
+
+	buf = malloc(vol_info->leb_size);
+	if (!buf)
+		return errmsg("cannot allocate %d bytes of memory", vol_info->leb_size);
+
+	if (!args.size) {
+		struct stat st;
+		err = stat(args.img, &st);
+		if (err < 0) {
+			errmsg("stat failed on \"%s\"", args.img);
+			goto out_free;
+		}
+
+		bytes = st.st_size;
+	} else
+		bytes = args.size;
+
+	if (bytes > vol_info->rsvd_bytes) {
+		errmsg("\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)",
+		       args.img, bytes, args.node, vol_info->rsvd_bytes);
+		goto out_free;
+	}
+
+	/* A hack to handle deprecated -B option */
+	if (args.broken_update)
+		bytes = 1;
+
+	fd = open(args.node, O_RDWR);
+	if (fd == -1) {
+		sys_errmsg("cannot open UBI volume \"%s\"", args.node);
+		goto out_free;
+	}
+
+	if (args.use_stdin)
+		ifd = STDIN_FILENO;
+	else {
+		ifd = open(args.img, O_RDONLY);
+		if (ifd == -1) {
+			sys_errmsg("cannot open \"%s\"", args.img);
+			goto out_close1;
+		}
+	}
+
+	err = ubi_update_start(libubi, fd, bytes);
+	if (err) {
+		sys_errmsg("cannot start volume \"%s\" update", args.node);
+		goto out_close;
+	}
+
+	while (bytes) {
+		int ret, to_copy = vol_info->leb_size;
+
+		if (to_copy > bytes)
+			to_copy = bytes;
+
+		ret = read(ifd, buf, to_copy);
+		if (ret <= 0) {
+			if (errno == EINTR) {
+				warnmsg("do not interrupt me!");
+				continue;
+			} else {
+				sys_errmsg("cannot read %d bytes from \"%s\"",
+						to_copy, args.img);
+				goto out_close;
+			}
+		}
+
+		err = ubi_write(fd, buf, ret);
+		if (err)
+			goto out_close;
+		bytes -= ret;
+	}
+
+	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;
+
+	libubi = libubi_open(1);
+	if (libubi == NULL) {
+		sys_errmsg("cannot open libubi");
+		goto out_libubi;
+	}
+
+	err = ubi_node_type(libubi, args.node);
+	if (err == 1) {
+		errmsg("\"%s\" is an UBI device node, not an UBI volume node",
+		       args.node);
+		goto out_libubi;
+	} else if (err < 0) {
+		errmsg("\"%s\" is not an UBI volume node", args.node);
+		goto out_libubi;
+	}
+
+	err = ubi_get_vol_info(libubi, args.node, &vol_info);
+	if (err) {
+		sys_errmsg("cannot get information about UBI volume \"%s\"",
+			   args.node);
+		goto out_libubi;
+	}
+
+	if (args.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/src/unubi.c b/ubi-utils/src/unubi.c
deleted file mode 100644
index 0f72b18..0000000
--- a/ubi-utils/src/unubi.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006, 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.
- */
-
-/*
- * Authors: Drake Dowsett, dowsett@de.ibm.com
- *          Frank Haverkamp, haver@vnet.ibm.com
- *
- * 1.2 Removed argp because we want to use uClibc.
- * 1.3 Minor cleanups.
- * 1.4 Meanwhile Drake had done a lot of changes, syncing those.
- * 1.5 Bugfixes, simplifications
- */
-
-/*
- * unubi  reads  an  image  file containing blocks of UBI headers and data
- * (such as produced from nand2bin) and rebuilds the volumes within.   The
- * default  operation  (when  no  flags are given) is to rebuild all valid
- * volumes found in the image. unubi  can  also  read  straight  from  the
- * onboard MTD device (ex. /dev/mtdblock/NAND).
- */
-
-/* TODO: consideration for dynamic vs. static volumes */
-
-#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 <limits.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <mtd/ubi-media.h>
-#include <mtd_swab.h>
-
-#include "crc32.h"
-#include "unubi_analyze.h"
-
-#define EXEC		"unubi"
-#define CONTACT		"haver@vnet.ibm.com"
-#define VERSION		"1.5"
-
-static char doc[] = "\nVersion: " VERSION "\n";
-static int debug = 0;
-
-static const char *optionsstr =
-"Extract volumes and/or analysis information from an UBI data file.\n"
-"When no parameters are flagged or given, the default operation is\n"
-"to rebuild all valid complete UBI volumes found within the image.\n"
-"\n"
-" OPERATIONS\n"
-"  -a, --analyze              Analyze image and create gnuplot graphs\n"
-"  -i, --info-table           Extract volume information tables\n"
-"  -r, --rebuild=<volume-id>  Extract and rebuild volume\n"
-"\n"
-" OPTIONS\n"
-"  -b, --blocksize=<block-size>   Specify size of eraseblocks in image in bytes\n"
-"                             (default 128KiB)\n"
-"  -d, --dir=<output-dir>     Specify output directory\n"
-"  -D, --debug                Enable debug output\n"
-"  -s, --headersize=<header-size>   Specify size reserved for metadata in eraseblock\n"
-	"                             in bytes (default 2048 Byte)\n"
- /* the -s option might be insufficient when using different vid
-    offset than what we used when writing this tool ... Better would
-    probably be --vid-hdr-offset or alike */
-"\n"
-" ADVANCED\n"
-"  -e, --eb-split             Generate individual eraseblock images (all\n"
-"                             eraseblocks)\n"
-"  -v, --vol-split            Generate individual eraseblock images (valid\n"
-"                             eraseblocks only)\n"
-"  -V, --vol-split!           Raw split by eraseblock (valid eraseblocks only)\n"
-"\n"
-"  -?, --help                 Give this help list\n"
-"      --usage                Give a short usage message\n"
-"      --version              Print program version\n"
-"\n";
-
-static const char *usage =
-"Usage: unubi [-aievV?] [-r <volume-id>] [-b <block-size>] [-d <output-dir>]\n"
-"            [-s <header-size>] [--analyze] [--info-table]\n"
-"            [--rebuild=<volume-id>] [--blocksize=<block-size>]\n"
-"            [--dir=<output-dir>] [--headersize=<header-size>] [--eb-split]\n"
-"            [--vol-split] [--vol-split!] [--help] [--usage] [--version]\n"
-"            image-file\n";
-
-#define ERR_MSG(fmt...)							\
-	fprintf(stderr, EXEC ": " fmt)
-
-#define SPLIT_DATA	1
-#define SPLIT_RAW	2
-
-#define DIR_FMT		"unubi_%s"
-#define KIB		1024
-#define MIB		(KIB * KIB)
-#define MAXPATH		KIB
-
-/* filenames */
-#define FN_INVAL	"%s/eb%04u%s"			/* invalid eraseblock */
-#define FN_NSURE	"%s/eb%04u_%03u_%03u_%03x%s"	/* unsure eraseblock */
-#define FN_VALID	"%s/eb%04u_%03u_%03u_%03x%s"	/* valid eraseblock */
-#define FN_VOLSP	"%s/vol%03u_%03u_%03u_%04zu"	/* split volume */
-#define FN_VOLWH	"%s/volume%03u"			/* whole volume */
-#define FN_VITBL	"%s/vol_info_table%zu"		/* vol info table */
-
-static uint32_t crc32_table[256];
-
-/* struct args:
- *	bsize		int, blocksize of image blocks
- *	hsize		int, eraseblock header size
- *	analyze		flag, when non-zero produce analysis
- *	eb_split	flag, when non-zero output eb####
- *			note: SPLIT_DATA vs. SPLIT_RAW
- *	vol_split	flag, when non-zero output vol###_####
- *			note: SPLIT_DATA vs. SPLIT_RAW
- *	odir_path	string, directory to place volumes in
- *	img_path	string, file to read as ubi image
- *	vols		int array of size UBI_MAX_VOLUMES, where a 1 can be
- *			written for each --rebuild flag in the index specified
- *			then the array can be counted and collapsed using
- *			count_set() and collapse()
- */
-struct args {
-	int analyze;
-	int itable;
-	uint32_t *vols;
-
-	size_t vid_hdr_offset;
-	size_t data_offset;
-	size_t bsize;		/* FIXME replace by vid_hdr/data offs? */
-	size_t hsize;
-
-	char *odir_path;
-	int eb_split;
-	int vol_split;
-	char *img_path;
-
-	char **options;
-};
-
-struct option long_options[] = {
-	{ .name = "rebuild", .has_arg = 1, .flag = NULL, .val = 'r' },
-	{ .name = "dir", .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ .name = "analyze", .has_arg = 0, .flag = NULL, .val = 'a' },
-	{ .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'b' },
-	{ .name = "eb-split", .has_arg = 0, .flag = NULL, .val = 'e' },
-	{ .name = "vol-split", .has_arg = 0, .flag = NULL, .val = 'v' },
-	{ .name = "vol-split!", .has_arg = 0, .flag = NULL, .val = 'e' },
-	{ .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 = 'J' },
-	{ NULL, 0, NULL, 0}
-};
-
-/**
- * parses out a numerical value from a string of numbers followed by:
- *	k, K, kib, KiB for kibibyte
- *	m, M, mib, MiB for mebibyte
- **/
-static uint32_t
-str_to_num(char *str)
-{
-	char *s;
-	ulong num;
-
-	s = str;
-	num = strtoul(s, &s, 0);
-
-	if (*s != '\0') {
-		if ((strcmp(s, "KiB") == 0) || (strcmp(s, "K") == 0) ||
-		    (strcmp(s, "kib") == 0) || (strcmp(s, "k") == 0))
-			num *= KIB;
-		else if ((strcmp(s, "MiB") == 0) || (strcmp(s, "M") == 0) ||
-		    (strcmp(s, "mib") == 0) || (strcmp(s, "m") == 0))
-			num *= MIB;
-		else
-			ERR_MSG("couldn't parse '%s', assuming %lu\n",
-				s, num);
-	}
-	return num;
-}
-
-static int
-parse_opt(int argc, char **argv, struct args *args)
-{
-	uint32_t i;
-
-	while (1) {
-		int key;
-
-		key = getopt_long(argc, argv, "ab:s:d:Deir:vV?J",
-				  long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'a': /* --analyze */
-			args->analyze = 1;
-			break;
-		case 'b': /* --block-size=<block-size> */
-			args->bsize = str_to_num(optarg);
-			break;
-		case 's': /* --header-size=<header-size> */
-			args->hsize = str_to_num(optarg);
-			break;
-		case 'd': /* --dir=<output-dir> */
-			args->odir_path = optarg;
-			break;
-		case 'D': /* --debug */
-			/* I wanted to use -v but that was already
-			   used ... */
-			debug = 1;
-			break;
-		case 'e': /* --eb-split */
-			args->eb_split = SPLIT_RAW;
-			break;
-		case 'i': /* --info-table */
-			args->itable = 1;
-			break;
-		case 'r': /* --rebuild=<volume-id> */
-			i = str_to_num(optarg);
-			if (i < UBI_MAX_VOLUMES)
-				args->vols[str_to_num(optarg)] = 1;
-			else {
-				ERR_MSG("volume-id out of bounds\n");
-				return -1;
-			}
-			break;
-		case 'v': /* --vol-split */
-			if (args->vol_split != SPLIT_RAW)
-				args->vol_split = SPLIT_DATA;
-			break;
-		case 'V': /* --vol-split! */
-			args->vol_split = SPLIT_RAW;
-			break;
-		case '?': /* help */
-			fprintf(stderr,	"Usage: unubi [OPTION...] "
-				"image-file\n%s%s\nReport bugs to %s\n",
-				doc, optionsstr, CONTACT);
-			exit(0);
-			break;
-		case 'J':
-			fprintf(stderr, "%s\n", VERSION);
-			exit(0);
-			break;
-		default:
-			fprintf(stderr, "%s", usage);
-			exit(-1);
-		}
-	}
-
-	/* FIXME I suppose hsize should be replaced! */
-	args->vid_hdr_offset = args->hsize - UBI_VID_HDR_SIZE;
-	args->data_offset = args->hsize;
-
-	if (optind < argc)
-		args->img_path = argv[optind++];
-	return 0;
-}
-
-
-/**
- * counts the number of indicies which are flagged in full_array;
- * full_array is an array of flags (1/0);
- **/
-static size_t
-count_set(uint32_t *full_array, size_t full_len)
-{
-	size_t count, i;
-
-	if (full_array == NULL)
-		return 0;
-
-	for (i = 0, count = 0; i < full_len; i++)
-		if (full_array[i] != 0)
-			count++;
-
-	return count;
-}
-
-
-/**
- * generates coll_array from full_array;
- * full_array is an array of flags (1/0);
- * coll_array is an array of the indicies in full_array which are flagged (1);
- **/
-static size_t
-collapse(uint32_t *full_array, size_t full_len,
-	 uint32_t *coll_array, size_t coll_len)
-{
-	size_t i, j;
-
-	if ((full_array == NULL) || (coll_array == NULL))
-		return 0;
-
-	for (i = 0, j = 0; (i < full_len) && (j < coll_len); i++)
-		if (full_array[i] != 0) {
-			coll_array[j] = i;
-			j++;
-		}
-
-	return j;
-}
-
-/**
- * data_crc: save the FILE* position, calculate the crc over a span,
- *	reset the position
- * returns non-zero when EOF encountered
- **/
-static int
-data_crc(FILE* fpin, size_t length, uint32_t *ret_crc)
-{
-	int rc;
-	size_t i;
-	char buf[length];
-	uint32_t crc;
-	fpos_t start;
-
-	rc = fgetpos(fpin, &start);
-	if (rc < 0)
-		return -1;
-
-	for (i = 0; i < length; i++) {
-		int c = fgetc(fpin);
-		if (c == EOF) {
-			ERR_MSG("unexpected EOF\n");
-			return -1;
-		}
-		buf[i] = (char)c;
-	}
-
-	rc = fsetpos(fpin, &start);
-	if (rc < 0)
-		return -1;
-
-	crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, length);
-	*ret_crc = crc;
-	return 0;
-}
-
-
-/**
- * reads data of size len from fpin and writes it to path
- **/
-static int
-extract_data(FILE* fpin, size_t len, const char *path)
-{
-	int rc;
-	size_t i;
-	FILE* fpout;
-
-	rc = 0;
-	fpout = NULL;
-
-	fpout = fopen(path, "wb");
-	if (fpout == NULL) {
-		ERR_MSG("couldn't open file for writing: %s\n", path);
-		rc = -1;
-		goto err;
-	}
-
-	for (i = 0; i < len; i++) {
-		int c = fgetc(fpin);
-		if (c == EOF) {
-			ERR_MSG("unexpected EOF while writing: %s\n", path);
-			rc = -2;
-			goto err;
-		}
-		c = fputc(c, fpout);
-		if (c == EOF) {
-			ERR_MSG("couldn't write: %s\n", path);
-			rc = -3;
-			goto err;
-		}
-	}
-
- err:
-	if (fpout != NULL)
-		fclose(fpout);
-	return rc;
-}
-
-
-/**
- * extract volume information table from block. saves and reloads fpin
- * position
- * returns -1 when a fpos set or get fails, otherwise <= -2 on other
- * failure and 0 on success
- **/
-static int
-extract_itable(FILE *fpin, struct eb_info *cur, size_t bsize, size_t num,
-	       const char *path)
-{
-	char filename[MAXPATH + 1];
-	int rc;
-	size_t i, max;
-	fpos_t temp;
-	FILE* fpout = NULL;
-	struct ubi_vtbl_record rec;
-
-	if (fpin == NULL || cur == NULL || path == NULL)
-		return -2;
-
-	/* remember position */
-	rc = fgetpos(fpin, &temp);
-	if (rc < 0)
-		return -1;
-
-	/* jump to top of eraseblock, skip to data section */
-	fsetpos(fpin, &cur->eb_top);
-	if (rc < 0)
-		return -1;
-	fseek(fpin, be32_to_cpu(cur->ec.data_offset), SEEK_CUR);
-
-	/* prepare output file */
-	if (be32_to_cpu(cur->vid.vol_id) != UBI_LAYOUT_VOLUME_ID)
-		return -2;
-	memset(filename, 0, MAXPATH + 1);
-	snprintf(filename, MAXPATH, FN_VITBL, path, num);
-	fpout = fopen(filename, "w");
-	if (fpout == NULL)
-		return -2;
-
-	/* loop through entries */
-	fprintf(fpout,
-		"index\trpebs\talign\ttype\tcrc\t\tname\n");
-	max = bsize - be32_to_cpu(cur->ec.data_offset);
-	for (i = 0; i < (max / sizeof(rec)); i++) {
-		int blank = 1;
-		char *ptr, *base;
-		char name[UBI_VOL_NAME_MAX + 1];
-		const char *type = "unknown\0";
-		uint32_t crc;
-
-		/* read record */
-		rc = fread(&rec, 1, sizeof(rec), fpin);
-		if (rc == 0)
-			break;
-		if (rc != sizeof(rec)) {
-			ERR_MSG("reading volume information "
-				"table record failed\n");
-			rc = -3;
-			goto exit;
-		}
-
-		/* check crc */
-		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &rec,
-				UBI_VTBL_RECORD_SIZE_CRC);
-		if (crc != be32_to_cpu(rec.crc))
-			continue;
-
-		/* check for empty */
-		base = (char *)&rec;
-		ptr = base;
-		while (blank &&
-		       ((unsigned)(ptr - base) < UBI_VTBL_RECORD_SIZE_CRC)) {
-			if (*ptr != 0)
-				blank = 0;
-			ptr++;
-		}
-
-		if (blank)
-			continue;
-
-		/* prep type string */
-		if (rec.vol_type == UBI_VID_DYNAMIC)
-			type = "dynamic\0";
-		else if (rec.vol_type == UBI_VID_STATIC)
-			type = "static\0";
-
-		/* prep name string */
-		rec.name[be16_to_cpu(rec.name_len)] = '\0';
-		sprintf(name, "%s", rec.name);
-
-		/* print record line to fpout */
-		fprintf(fpout, "%zu\t%u\t%u\t%s\t0x%08x\t%s\n",
-			i,
-			be32_to_cpu(rec.reserved_pebs),
-			be32_to_cpu(rec.alignment),
-			type,
-			be32_to_cpu(rec.crc),
-			name);
-	}
-
- exit:
-	/* reset position */
-	if (fsetpos(fpin, &temp) < 0)
-		rc = -1;
-
-	if (fpout != NULL)
-		fclose(fpout);
-
-	return rc;
-}
-
-
-/**
- * using eb chain, tries to rebuild the data of volume at vol_id, or for all
- * the known volumes, if vol_id is NULL;
- **/
-static int
-rebuild_volume(FILE * fpin, uint32_t *vol_id, struct eb_info **head,
-	       const char *path, size_t block_size, size_t header_size)
-{
-	char filename[MAXPATH];
-	int rc;
-	uint32_t vol, num, data_size;
-	FILE* fpout;
-	struct eb_info *cur;
-
-	rc = 0;
-
-	if ((fpin == NULL) || (head == NULL) || (*head == NULL))
-		return 0;
-
-	/* when vol_id is null, then do all  */
-	if (vol_id == NULL) {
-		cur = *head;
-		vol = be32_to_cpu(cur->vid.vol_id);
-	} else {
-		vol = *vol_id;
-		eb_chain_position(head, vol, NULL, &cur);
-		if (cur == NULL) {
-			if (debug)
-				ERR_MSG("no valid volume %d was found\n", vol);
-			return -1;
-		}
-	}
-
-	num = 0;
-	snprintf(filename, MAXPATH, FN_VOLWH, path, vol);
-	fpout = fopen(filename, "wb");
-	if (fpout == NULL) {
-		ERR_MSG("couldn't open file for writing: %s\n", filename);
-		return -1;
-	}
-
-	while (cur != NULL) {
-		size_t i;
-
-		if (be32_to_cpu(cur->vid.vol_id) != vol) {
-			/* close out file */
-			fclose(fpout);
-
-			/* only stay around if that was the only volume */
-			if (vol_id != NULL)
-				goto out;
-
-			/* begin with next */
-			vol = be32_to_cpu(cur->vid.vol_id);
-			num = 0;
-			snprintf(filename, MAXPATH, FN_VOLWH, path, vol);
-			fpout = fopen(filename, "wb");
-			if (fpout == NULL) {
-				ERR_MSG("couldn't open file for writing: %s\n",
-					filename);
-				return -1;
-			}
-		}
-
-		while (num < be32_to_cpu(cur->vid.lnum)) {
-			/* FIXME haver: I hope an empty block is
-			   written out so that the binary has no holes
-			   ... */
-			if (debug)
-				ERR_MSG("missing valid block %d for volume %d\n",
-					num, vol);
-			num++;
-		}
-
-		rc = fsetpos(fpin, &(cur->eb_top));
-		if (rc < 0)
-			goto out;
-		fseek(fpin, be32_to_cpu(cur->ec.data_offset), SEEK_CUR);
-
-		if (cur->vid.vol_type == UBI_VID_DYNAMIC)
-			/* FIXME It might be that alignment has influence */
-			data_size = block_size - header_size;
-		else
-			data_size = be32_to_cpu(cur->vid.data_size);
-
-		for (i = 0; i < data_size; i++) {
-			int c = fgetc(fpin);
-			if (c == EOF) {
-				ERR_MSG("unexpected EOF while writing: %s\n",
-					filename);
-				rc = -2;
-				goto out;
-			}
-			c = fputc(c, fpout);
-			if (c == EOF) {
-				ERR_MSG("couldn't write: %s\n", filename);
-				rc = -3;
-				goto out;
-			}
-		}
-
-		cur = cur->next;
-		num++;
-	}
-
- out:
-	if (vol_id == NULL)
-		fclose(fpout);
-	return rc;
-}
-
-
-/**
- * traverses FILE* trying to load complete, valid and accurate header data
- * into the eb chain;
- **/
-static int
-unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
-{
-	char filename[MAXPATH + 1];
-	char reason[MAXPATH + 1];
-	int rc;
-	size_t i, count, itable_num;
-	/* relations:
-	 * cur ~ head
-	 * next ~ first */
-	struct eb_info *head, *cur, *first, *next;
-	struct eb_info **next_ptr;
-
-	rc = 0;
-	count = 0;
-	itable_num = 0;
-	head = NULL;
-	first = NULL;
-	next = NULL;
-	cur = malloc(sizeof(*cur));
-	if (cur == NULL) {
-		ERR_MSG("out of memory\n");
-		rc = -ENOMEM;
-		goto err;
-	}
-	memset(cur, 0, sizeof(*cur));
-
-	fgetpos(fpin, &(cur->eb_top));
-	while (1) {
-		const char *raw_path;
-		uint32_t crc;
-
-		cur->phys_addr = ftell(fpin);
-		cur->phys_block = cur->phys_addr / a->bsize;
-		cur->data_crc_ok = 0;
-		cur->ec_crc_ok   = 0;
-		cur->vid_crc_ok  = 0;
-
-		memset(filename, 0, MAXPATH + 1);
-		memset(reason, 0, MAXPATH + 1);
-
-		/* in case of an incomplete ec header */
-		raw_path = FN_INVAL;
-
-		/* read erasecounter header */
-		rc = fread(&cur->ec, 1, sizeof(cur->ec), fpin);
-		if (rc == 0)
-			goto out; /* EOF */
-		if (rc != sizeof(cur->ec)) {
-			ERR_MSG("reading ec-hdr failed\n");
-			rc = -1;
-			goto err;
-		}
-
-		/* check erasecounter header magic */
-		if (be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) {
-			snprintf(reason, MAXPATH, ".invalid.ec_magic");
-			goto invalid;
-		}
-
-		/* check erasecounter header crc */
-		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->ec),
-				UBI_EC_HDR_SIZE_CRC);
-		if (be32_to_cpu(cur->ec.hdr_crc) != crc) {
-			snprintf(reason, MAXPATH, ".invalid.ec_hdr_crc");
-			goto invalid;
-		}
-
-		/* read volume id header */
-		rc = fsetpos(fpin, &(cur->eb_top));
-		if (rc != 0)
-			goto err;
-		fseek(fpin, be32_to_cpu(cur->ec.vid_hdr_offset), SEEK_CUR);
-		rc = fread(&cur->vid, 1, sizeof(cur->vid), fpin);
-		if (rc == 0)
-			goto out; /* EOF */
-		if (rc != sizeof(cur->vid)) {
-			ERR_MSG("reading vid-hdr failed\n");
-			rc = -1;
-			goto err;
-		}
-
-		/* if the magic number is 0xFFFFFFFF, then it's very likely
-		 * that the volume is empty */
-		if (be32_to_cpu(cur->vid.magic) == 0xffffffff) {
-			snprintf(reason, MAXPATH, ".empty");
-			goto invalid;
-		}
-
-		/* vol_id should be in bounds */
-		if ((be32_to_cpu(cur->vid.vol_id) >= UBI_MAX_VOLUMES) &&
-		    (be32_to_cpu(cur->vid.vol_id) <
-		     UBI_INTERNAL_VOL_START)) {
-			snprintf(reason, MAXPATH, ".invalid");
-			goto invalid;
-		} else
-			raw_path = FN_NSURE;
-
-		/* check volume id header magic */
-		if (be32_to_cpu(cur->vid.magic) != UBI_VID_HDR_MAGIC) {
-			snprintf(reason, MAXPATH, ".invalid.vid_magic");
-			goto invalid;
-		}
-		cur->ec_crc_ok = 1;
-
-		/* check volume id header crc */
-		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->vid),
-				UBI_VID_HDR_SIZE_CRC);
-		if (be32_to_cpu(cur->vid.hdr_crc) != crc) {
-			snprintf(reason, MAXPATH, ".invalid.vid_hdr_crc");
-			goto invalid;
-		}
-		cur->vid_crc_ok = 1;
-
-		/* check data crc, but only for a static volume */
-		if (cur->vid.vol_type == UBI_VID_STATIC) {
-			rc = data_crc(fpin, be32_to_cpu(cur->vid.data_size),
-				      &crc);
-			if (rc < 0)
-				goto err;
-			if (be32_to_cpu(cur->vid.data_crc) != crc) {
-				snprintf(reason, MAXPATH, ".invalid.data_crc");
-				goto invalid;
-			}
-			cur->data_crc_ok = 1;
-		}
-
-		/* enlist this vol, it's valid */
-		raw_path = FN_VALID;
-		cur->linear = count;
-		rc = eb_chain_insert(&head, cur);
-		if (rc < 0) {
-			if (rc == -ENOMEM) {
-				ERR_MSG("out of memory\n");
-				goto err;
-			}
-			ERR_MSG("unknown and unexpected error, please contact "
-				CONTACT "\n");
-			goto err;
-		}
-
-		/* extract info-table */
-		if (a->itable &&
-		    (be32_to_cpu(cur->vid.vol_id) == UBI_LAYOUT_VOLUME_ID)) {
-			extract_itable(fpin, cur, a->bsize,
-				       itable_num, a->odir_path);
-			itable_num++;
-		}
-
-		/* split volumes */
-		if (a->vol_split) {
-			size_t size = 0;
-
-			rc = fsetpos(fpin, &(cur->eb_top));
-			if (rc != 0)
-				goto err;
-
-			/*
-			 * FIXME For dynamic UBI volumes we must write
-			 * the maximum available data. The
-			 * vid.data_size field is not used in this
-			 * case. The dynamic volume user is
-			 * responsible for the content.
-			 */
-			if (a->vol_split == SPLIT_DATA) {
-				/* Write only data section */
-				if (cur->vid.vol_type == UBI_VID_DYNAMIC) {
-					/* FIXME Formular is not
-					   always right ... */
-					size = a->bsize - a->hsize;
-				} else
-					size = be32_to_cpu(cur->vid.data_size);
-
-				fseek(fpin,
-				      be32_to_cpu(cur->ec.data_offset),
-				      SEEK_CUR);
-			}
-			else if (a->vol_split == SPLIT_RAW)
-				/* write entire eraseblock */
-				size = a->bsize;
-
-			snprintf(filename, MAXPATH, FN_VOLSP,
-				 a->odir_path,
-				 be32_to_cpu(cur->vid.vol_id),
-				 be32_to_cpu(cur->vid.lnum),
-				 be32_to_cpu(cur->vid.leb_ver), count);
-			rc = extract_data(fpin, size, filename);
-			if (rc < 0)
-				goto err;
-		}
-
- invalid:
-		/* split eraseblocks */
-		if (a->eb_split) {
-			/* jump to top of block */
-			rc = fsetpos(fpin, &(cur->eb_top));
-			if (rc != 0)
-				goto err;
-
-			if (strcmp(raw_path, FN_INVAL) == 0)
-				snprintf(filename, MAXPATH, raw_path,
-					 a->odir_path, count, reason);
-			else
-				snprintf(filename, MAXPATH, raw_path,
-					 a->odir_path,
-					 count,
-					 be32_to_cpu(cur->vid.vol_id),
-					 be32_to_cpu(cur->vid.lnum),
-					 be32_to_cpu(cur->vid.leb_ver),
-					 reason);
-
-			rc = extract_data(fpin, a->bsize, filename);
-			if (rc < 0)
-				goto err;
-		}
-
-		/* append to simple linked list */
-		if (first == NULL)
-			next_ptr = &first;
-		else
-			next_ptr = &next->next;
-
-		*next_ptr = malloc(sizeof(**next_ptr));
-		if (*next_ptr == NULL) {
-			ERR_MSG("out of memory\n");
-			rc = -ENOMEM;
-			goto err;
-		}
-		memset(*next_ptr, 0, sizeof(**next_ptr));
-
-		next = *next_ptr;
-		memcpy(next, cur, sizeof(*next));
-		next->next = NULL;
-
-		count++;
-		rc = fsetpos(fpin, &(cur->eb_top));
-		if (rc != 0)
-			goto err;
-		fseek(fpin, a->bsize, SEEK_CUR);
-		memset(cur, 0, sizeof(*cur));
-
-		fgetpos(fpin, &(cur->eb_top));
-	}
-
- out:
-	for (i = 0; i < vc; i++) {
-		rc = rebuild_volume(fpin, &vols[i], &head, a->odir_path,
-			       a->bsize, a->hsize);
-		if (rc < 0)
-			goto err;
-	}
-
-	/* if there were no volumes specified, rebuild them all,
-	 * UNLESS eb_ or vol_ split or analyze was specified */
-	if ((vc == 0) && (!a->eb_split) && (!a->vol_split) &&
-	    (!a->analyze) && (!a->itable)) {
-		rc = rebuild_volume(fpin, NULL, &head, a->odir_path, a->bsize,
-				    a->hsize);
-		if (rc < 0)
-			goto err;
-	}
-
- err:
-	free(cur);
-
-	if (a->analyze) {
-		char fname[PATH_MAX + 1];
-		FILE *fp;
-
-		unubi_analyze(&head, first, a->odir_path);
-
-		/* prepare output files */
-		memset(fname, 0, PATH_MAX + 1);
-		snprintf(fname, PATH_MAX, "%s/%s", a->odir_path, FN_EH_STAT);
-		fp = fopen(fname, "w");
-		if (fp != NULL) {
-			eb_chain_print(fp, head);
-			fclose(fp);
-		}
-	}
-	eb_chain_destroy(&head);
-	eb_chain_destroy(&first);
-
-	return rc;
-}
-
-
-/**
- * handles command line arguments, then calls unubi_volumes
- **/
-int
-main(int argc, char *argv[])
-{
-	int rc, free_a_odir;
-	size_t vols_len;
-	uint32_t *vols;
-	FILE* fpin;
-	struct args a;
-
-	rc = 0;
-	free_a_odir = 0;
-	vols_len = 0;
-	vols = NULL;
-	fpin = NULL;
-	init_crc32_table(crc32_table);
-
-	/* setup struct args a */
-	memset(&a, 0, sizeof(a));
-	a.bsize = 128 * KIB;
-	a.hsize = 2 * KIB;
-	a.vols = malloc(sizeof(*a.vols) * UBI_MAX_VOLUMES);
-	if (a.vols == NULL) {
-		ERR_MSG("out of memory\n");
-		rc = ENOMEM;
-		goto err;
-	}
-	memset(a.vols, 0, sizeof(*a.vols) * UBI_MAX_VOLUMES);
-
-	/* parse args and check for validity */
-	parse_opt(argc, argv, &a);
-	if (a.img_path == NULL) {
-		ERR_MSG("no image file specified\n");
-		rc = EINVAL;
-		goto err;
-	}
-	else if (a.odir_path == NULL) {
-		char *ptr;
-		int len;
-
-		ptr = strrchr(a.img_path, '/');
-		if (ptr == NULL)
-			ptr = a.img_path;
-		else
-			ptr++;
-
-		len = strlen(DIR_FMT) + strlen(ptr);
-		free_a_odir = 1;
-		a.odir_path = malloc(sizeof(*a.odir_path) * len);
-		if (a.odir_path == NULL) {
-			ERR_MSG("out of memory\n");
-			rc = ENOMEM;
-			goto err;
-		}
-		snprintf(a.odir_path, len, DIR_FMT, ptr);
-	}
-
-	fpin = fopen(a.img_path, "rb");
-	if (fpin == NULL) {
-		ERR_MSG("couldn't open file for reading: "
-			"%s\n", a.img_path);
-		rc = EINVAL;
-		goto err;
-	}
-
-	rc = mkdir(a.odir_path, 0777);
-	if ((rc < 0) && (errno != EEXIST)) {
-		ERR_MSG("couldn't create ouput directory: "
-			"%s\n", a.odir_path);
-		rc = -rc;
-		goto err;
-	}
-
-	/* fill in vols array */
-	vols_len = count_set(a.vols, UBI_MAX_VOLUMES);
-	if (vols_len > 0) {
-		vols = malloc(sizeof(*vols) * vols_len);
-		if (vols == NULL) {
-			ERR_MSG("out of memory\n");
-			rc = ENOMEM;
-			goto err;
-		}
-		collapse(a.vols, UBI_MAX_VOLUMES, vols, vols_len);
-	}
-
-	/* unubi volumes */
-	rc = unubi_volumes(fpin, vols, vols_len, &a);
-	if (rc < 0) {
-		/* ERR_MSG("error encountered while working on image file: "
-		   "%s\n", a.img_path); */
-		rc = -rc;
-		goto err;
-	}
-
- err:
-	free(a.vols);
-	if (free_a_odir != 0)
-		free(a.odir_path);
-	if (fpin != NULL)
-		fclose(fpin);
-	if (vols_len > 0)
-		free(vols);
-	return rc;
-}
diff --git a/ubi-utils/src/unubi_analyze.c b/ubi-utils/src/unubi_analyze.c
deleted file mode 100644
index ceaa85f..0000000
--- a/ubi-utils/src/unubi_analyze.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006, 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.
- */
-
-/*
- * Authors: Drake Dowsett, dowsett@de.ibm.com
- * Contact: Andreas Arnez, arnez@de.ibm.com
- *
- * unubi uses the following functions to generate analysis output based on
- * the header information in a raw-UBI image
- */
-
-/*
- * TODO: use OOB data to check for eraseblock validity in NAND images
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <mtd_swab.h>
-
-#include "unubi_analyze.h"
-#include "crc32.h"
-
-#define EC_X_INT	50
-
-/**
- * intcmp - function needed by qsort to order integers
- **/
-int intcmp(const void *a, const void *b)
-{
-	int A = *(int *)a;
-	int B = *(int *)b;
-	return A - B;
-}
-
-int longcmp(const void *a, const void *b)
-{
-	long long A = *(long long *)a;
-	long long B = *(long long *)b;
-	return A - B;
-}
-
-
-/**
- * unubi_analyze_group_index - finds the normalized index in an array
- * item:	look for this item in the array
- * array:	array to search through
- * size:	length of the array
- * array should be sorted for this algorithm to perform properly;
- * if the item is not found returns -1, otherwise return value is the
- * index in the array (note this contricts the array size to 2^32-1);
- **/
-int
-norm_index(uint32_t item, uint32_t *array, size_t length)
-{
-	size_t i, index;
-
-	for (index = 0, i = 0; i < length; i++) {
-		if ((i != 0) && (array[i] != array[i - 1]))
-			index++;
-
-		if (item == array[i])
-			return index;
-	}
-
-	return -1;
-}
-
-
-/**
- * unubi_analyze_ec_hdr - generate data table and plot script
- * first:	head of simple linked list
- * path:	folder to write into
- * generates a data file containing the eraseblock index in the image
- * and the erase counter found in its ec header;
- * if the crc check fails, the line is commented out in the data file;
- * also generates a simple gnuplot sript for quickly viewing one
- * display of the data file;
- **/
-int
-unubi_analyze_ec_hdr(struct eb_info *first, const char *path)
-{
-	char filename[PATH_MAX + 1];
-	size_t count, eraseblocks;
-	uint32_t crc, crc32_table[256];
-	uint64_t *erase_counts;
-	FILE* fpdata;
-	FILE* fpplot;
-	struct eb_info *cur;
-
-	if (first == NULL)
-		return -1;
-
-	/* crc check still needed for `first' linked list */
-	init_crc32_table(crc32_table);
-
-	/* prepare output files */
-	memset(filename, 0, PATH_MAX + 1);
-	snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_DATA);
-	fpdata = fopen(filename, "w");
-	if (fpdata == NULL)
-		return -1;
-
-	memset(filename, 0, PATH_MAX + 1);
-	snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_PLOT);
-	fpplot = fopen(filename, "w");
-	if (fpplot == NULL) {
-		fclose(fpdata);
-		return -1;
-	}
-
-	/* make executable */
-	chmod(filename, 0755);
-
-	/* first run: count elements */
-	count = 0;
-	cur = first;
-	while (cur != NULL) {
-		cur = cur->next;
-		count++;
-	}
-	eraseblocks = count;
-
-	erase_counts = malloc(eraseblocks * sizeof(*erase_counts));
-	if (!erase_counts) {
-		perror("out of memory");
-		exit(EXIT_FAILURE);
-	}
-
-	memset(erase_counts, 0, eraseblocks * sizeof(*erase_counts));
-
-	/* second run: populate array to sort */
-	count = 0;
-	cur = first;
-	while (cur != NULL) {
-		erase_counts[count] = be64_to_cpu(cur->ec.ec);
-		cur = cur->next;
-		count++;
-	}
-	qsort(erase_counts, eraseblocks, sizeof(*erase_counts),
-	      (void *)longcmp);
-
-	/* third run: generate data file */
-	count = 0;
-	cur = first;
-	fprintf(fpdata, "# eraseblock_no actual_erase_count "
-			"sorted_erase_count\n");
-	while (cur != NULL) {
-		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &cur->ec,
-				UBI_EC_HDR_SIZE_CRC);
-
-		if ((be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) ||
-		    (crc != be32_to_cpu(cur->ec.hdr_crc)))
-			fprintf(fpdata, "# ");
-
-		fprintf(fpdata, "%zu %llu %llu", count,
-			(unsigned long long)be64_to_cpu(cur->ec.ec),
-			(unsigned long long)erase_counts[count]);
-
-		if (be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC)
-			fprintf(fpdata, " ## bad magic: %08x",
-				be32_to_cpu(cur->ec.magic));
-
-		if (crc != be32_to_cpu(cur->ec.hdr_crc))
-			fprintf(fpdata, " ## CRC mismatch: given=%08x, "
-				"calc=%08x", be32_to_cpu(cur->ec.hdr_crc),
-				crc);
-
-		fprintf(fpdata, "\n");
-
-		cur = cur->next;
-		count++;
-	}
-	fclose(fpdata);
-
-	fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n");
-	fprintf(fpplot, "set xlabel \"eraseblock\"\n");
-
-	/* fourth run: generate plot file xtics */
-	count = 0;
-	cur = first;
-	fprintf(fpplot, "set xtics (");
-	while (cur != NULL) {
-		if ((count % EC_X_INT) == 0) {
-			if (count > 0)
-				fprintf(fpplot, ", ");
-			fprintf(fpplot, "%zd", count);
-		}
-
-		cur = cur->next;
-		count++;
-	}
-	fprintf(fpplot, ")\n");
-
-	fprintf(fpplot, "set ylabel \"erase count\"\n");
-	fprintf(fpplot, "set xrange [-1:%zu]\n", eraseblocks + 1);
-	fprintf(fpplot, "# set yrange [-1:%llu]\n",
-		(unsigned long long)erase_counts[eraseblocks - 1] + 1);
-	fprintf(fpplot, "plot \"%s\" u 1:2 t \"unsorted: %s\" with boxes\n",
-		FN_EH_DATA, FN_EH_DATA);
-	fprintf(fpplot, "# replot \"%s\" u 1:3 t \"sorted: %s\" with lines\n",
-		FN_EH_DATA, FN_EH_DATA);
-	fprintf(fpplot, "pause -1 \"press ENTER\"\n");
-
-	fclose(fpplot);
-
-	return 0;
-}
-
-
-/**
- * unubi_analyze_vid_hdr - generate data table and plot script
- * head:	head of complex linked list (eb_chain)
- * path:	folder to write into
- * generates a data file containing the volume id, logical number, leb version,
- * and data size from the vid header;
- * all eraseblocks listed in the eb_chain are valid (checked in unubi);
- * also generates a simple gnuplot sript for quickly viewing one
- * display of the data file;
- **/
-int
-unubi_analyze_vid_hdr(struct eb_info **head, const char *path)
-{
-	char filename[PATH_MAX + 1];
-	int rc, y1, y2;
-	size_t count, step, breadth;
-	uint32_t *leb_versions, *data_sizes;
-	FILE* fpdata;
-	FILE* fpplot;
-	struct eb_info *cur;
-
-	if (head == NULL || *head == NULL)
-		return -1;
-
-	rc = 0;
-	fpdata = NULL;
-	fpplot = NULL;
-	data_sizes = NULL;
-	leb_versions = NULL;
-
-	/* prepare output files */
-	memset(filename, 0, PATH_MAX + 1);
-	snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_DATA);
-	fpdata = fopen(filename, "w");
-	if (fpdata == NULL) {
-		rc = -1;
-		goto exit;
-	}
-
-	memset(filename, 0, PATH_MAX + 1);
-	snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_PLOT);
-	fpplot = fopen(filename, "w");
-	if (fpplot == NULL) {
-		rc = -1;
-		goto exit;
-	}
-
-	/* make executable */
-	chmod(filename, 0755);
-
-	/* first run: count elements */
-	count = 0;
-	cur = *head;
-	while (cur != NULL) {
-		cur = cur->next;
-		count++;
-	}
-	breadth = count;
-
-	leb_versions = malloc(breadth * sizeof(uint32_t));
-	if (leb_versions == NULL) {
-		rc = -1;
-		goto exit;
-	}
-	memset(leb_versions, 0, breadth * sizeof(uint32_t));
-
-	data_sizes = malloc(breadth * sizeof(uint32_t));
-	if (data_sizes == NULL) {
-		rc = -1;
-		goto exit;
-	}
-	memset(data_sizes, 0, breadth * sizeof(*data_sizes));
-
-	/* second run: populate arrays to sort */
-	count = 0;
-	cur = *head;
-	while (cur != NULL) {
-		leb_versions[count] = be32_to_cpu(cur->vid.leb_ver);
-		data_sizes[count] = be32_to_cpu(cur->vid.data_size);
-		cur = cur->next;
-		count++;
-	}
-	qsort(leb_versions, breadth, sizeof(*leb_versions), (void *)intcmp);
-	qsort(data_sizes, breadth, sizeof(*data_sizes), (void *)intcmp);
-
-	/* third run: generate data file */
-	count = 0;
-	cur = *head;
-	fprintf(fpdata, "# x_axis vol_id lnum   y1_axis leb_ver   "
-		"y2_axis data_size\n");
-	while (cur != NULL) {
-		y1 = norm_index(be32_to_cpu(cur->vid.leb_ver), leb_versions,
-				breadth);
-		y2 = norm_index(be32_to_cpu(cur->vid.data_size), data_sizes,
-				breadth);
-
-		if ((y1 == -1) || (y2 == -1)) {
-			rc = -1;
-			goto exit;
-		}
-
-		fprintf(fpdata, "%zu %u %u   %u %u   %u %u\n",
-			count,
-			be32_to_cpu(cur->vid.vol_id),
-			be32_to_cpu(cur->vid.lnum),
-			y1,
-			be32_to_cpu(cur->vid.leb_ver),
-			y2,
-			be32_to_cpu(cur->vid.data_size));
-		cur = cur->next;
-		count++;
-	}
-
-	fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n");
-	fprintf(fpplot, "set xlabel \"volume\"\n");
-
-	/* fourth run: generate plot file xtics */
-	count = 0;
-	step = 0;
-	cur = *head;
-	fprintf(fpplot, "set xtics (");
-	while (cur != NULL) {
-		if (count > 0)
-			fprintf(fpplot, ", ");
-		if (step != be32_to_cpu(cur->vid.vol_id)) {
-			step = be32_to_cpu(cur->vid.vol_id);
-			fprintf(fpplot, "\"%zd\" %zd 0", step, count);
-		}
-		else
-			fprintf(fpplot, "\"%d\" %zd 1",
-				be32_to_cpu(cur->vid.lnum), count);
-		cur = cur->next;
-		count++;
-	}
-	fprintf(fpplot, ")\n");
-	fprintf(fpplot, "set nox2tics\n");
-
-	/* fifth run: generate plot file ytics */
-	count = 0;
-	cur = *head;
-	fprintf(fpplot, "set ylabel \"leb version\"\n");
-	fprintf(fpplot, "set ytics (");
-	while (cur->next != NULL) {
-		y1 = norm_index(be32_to_cpu(cur->vid.leb_ver), leb_versions,
-				breadth);
-
-		if (y1 == -1) {
-			rc = -1;
-			goto exit;
-		}
-
-		if (count > 0)
-			fprintf(fpplot, ", ");
-
-		fprintf(fpplot, "\"%u\" %u", be32_to_cpu(cur->vid.leb_ver),
-			y1);
-
-		cur = cur->next;
-		count++;
-	}
-	fprintf(fpplot, ")\n");
-
-	/* sixth run: generate plot file y2tics */
-	count = 0;
-	cur = *head;
-	fprintf(fpplot, "set y2label \"data size\"\n");
-	fprintf(fpplot, "set y2tics (");
-	while (cur != NULL) {
-		y2 = norm_index(be32_to_cpu(cur->vid.data_size),
-				data_sizes, breadth);
-
-		if (y2 == -1) {
-			rc = -1;
-			goto exit;
-		}
-
-		if (count > 0)
-			fprintf(fpplot, ", ");
-
-		fprintf(fpplot, "\"%u\" %u", be32_to_cpu(cur->vid.data_size),
-			y2);
-
-		cur = cur->next;
-		count++;
-	}
-	fprintf(fpplot, ")\n");
-
-	y1 = norm_index(leb_versions[breadth - 1], leb_versions, breadth);
-	y2 = norm_index(data_sizes[breadth - 1], data_sizes, breadth);
-	fprintf(fpplot, "set xrange [-1:%zu]\n", count + 1);
-	fprintf(fpplot, "set yrange [-1:%u]\n", y1 + 1);
-	fprintf(fpplot, "set y2range [-1:%u]\n", y2 + 1);
-	fprintf(fpplot, "plot \"%s\" u 1:4 t \"leb version: %s\" "
-			"axes x1y1 with lp\n", FN_VH_DATA, FN_VH_DATA);
-	fprintf(fpplot, "replot \"%s\" u 1:6 t \"data size: %s\" "
-			"axes x1y2 with lp\n", FN_VH_DATA, FN_VH_DATA);
-	fprintf(fpplot, "pause -1 \"press ENTER\"\n");
-
- exit:
-	if (fpdata != NULL)
-		fclose(fpdata);
-	if (fpplot != NULL)
-		fclose(fpplot);
-	if (data_sizes != NULL)
-		free(data_sizes);
-	if (leb_versions != NULL)
-		free(leb_versions);
-
-	return rc;
-}
-
-
-/**
- * unubi_analyze - run all analyses
- * head:	eb_chain head
- * first:	simple linked list of eraseblock headers (use .next)
- * path:	directory (without trailing slash) to output to
- * returns 0 upon successful completion, or -1 otherwise
- **/
-int
-unubi_analyze(struct eb_info **head, struct eb_info *first, const char *path)
-{
-	int ec_rc, vid_rc;
-
-	if (path == NULL)
-		return -1;
-
-	ec_rc = unubi_analyze_ec_hdr(first, path);
-	vid_rc = unubi_analyze_vid_hdr(head, path);
-	if (ec_rc < 0 || vid_rc < 0)
-		return -1;
-
-	return 0;
-}
diff --git a/ubi-utils/src/unubi_analyze.h b/ubi-utils/src/unubi_analyze.h
deleted file mode 100644
index c478f53..0000000
--- a/ubi-utils/src/unubi_analyze.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006, 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 __UNUBI_ANALYZE_H__
-#define __UNUBI_ANALYZE_H__
-
-/*
- * Author:  Drake Dowsett
- * Contact: Andreas Arnez (arnez@de.ibm.com)
- *
- * Eraseblock Chain
- *
- * A linked list structure to order eraseblocks by volume and logical number
- * and to update by version number. Doesn't contain actual eraseblock data
- * but rather the erasecounter and volume id headers as well as a position
- * indicator.
- *
- * Diagram Example:
- *
- * [V1.0v0]->[V1.1v2]->[V1.2v1]->[V2.0v2]->[V2.1v0]->[V2.2v1]->NULL
- *     |         |         |         |         |         |
- *   NULL    [V1.1v1]  [V1.2v0]  [V2.0v1]    NULL    [V2.2v0]
- *               |         |         |                   |
- *           [V1.1v0]    NULL    [V2.0v0]              NULL
- *               |                   |
- *             NULL                NULL
- *
- * [VA.BvC] represents the eb_info for the eraseblock with the vol_id A,
- * lnum B and leb_ver C
- * -> represents the `next' pointer
- * | represents the `older' pointer
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <mtd/ubi-media.h>
-
-#define FN_EH_STAT      "analysis_blocks.txt"
-#define FN_EH_DATA	"analysis_ec_hdr.data"
-#define FN_EH_PLOT	"analysis_ec_hdr.plot"
-#define FN_VH_DATA	"analysis_vid_hdr.data"
-#define FN_VH_PLOT	"analysis_vid_hdr.plot"
-
-struct eb_info {
-	struct ubi_ec_hdr ec;
-	struct ubi_vid_hdr vid;
-
-	fpos_t eb_top;
-	uint32_t linear;
-	int ec_crc_ok;
-	int vid_crc_ok;
-	int data_crc_ok;
-	uint32_t phys_addr;
-	int phys_block;
-
-	struct eb_info *next;
-	struct eb_info *older;
-};
-
-int eb_chain_insert(struct eb_info **head, struct eb_info *item);
-
-int eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum,
-		      struct eb_info **pos);
-
-int eb_chain_print(FILE *stream, struct eb_info *head);
-
-int eb_chain_destroy(struct eb_info **head);
-
-int unubi_analyze(struct eb_info **head, struct eb_info *first,
-		  const char *path);
-
-#endif /* __UNUBI_ANALYZE_H__ */
diff --git a/ubi-utils/testcases.txt b/ubi-utils/testcases.txt
deleted file mode 100644
index dcc1c35..0000000
--- a/ubi-utils/testcases.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-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.
-- 
cgit v1.2.3