From 22f5fe49d60ea43524a902408b3112a78f2c5aae Mon Sep 17 00:00:00 2001
From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Date: Tue, 22 Jan 2008 16:02:52 +0200
Subject: ubi-utils: massive changes

This commit basically removes most of the old ubi utilities
as they are barely maintainamble.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
---
 ubi-utils/src/bootenv.c       |   8 +-
 ubi-utils/src/common.h        |   1 +
 ubi-utils/src/crc32.c         | 156 +++++-----
 ubi-utils/src/crc32.h         |  47 +--
 ubi-utils/src/libpfi.c        | 628 +++++++++++++++++++++++++++++++++++++++
 ubi-utils/src/libubigen.c     | 665 ++++++++++++++++--------------------------
 ubi-utils/src/list.c          |  52 ++--
 ubi-utils/src/list.h          |  55 ++--
 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       | 465 ++++++-----------------------
 ubi-utils/src/reader.c        | 482 ------------------------------
 ubi-utils/src/reader.h        |  87 ------
 ubi-utils/src/ubicrc32.c      |   9 +-
 ubi-utils/src/ubigen.h        | 150 ----------
 ubi-utils/src/unubi.c         |  14 +-
 ubi-utils/src/unubi_analyze.c |   8 +-
 19 files changed, 1123 insertions(+), 2563 deletions(-)
 create mode 100644 ubi-utils/src/libpfi.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/reader.c
 delete mode 100644 ubi-utils/src/reader.h
 delete mode 100644 ubi-utils/src/ubigen.h

(limited to 'ubi-utils/src')

diff --git a/ubi-utils/src/bootenv.c b/ubi-utils/src/bootenv.c
index a6dd4de..5a4205f 100644
--- a/ubi-utils/src/bootenv.c
+++ b/ubi-utils/src/bootenv.c
@@ -282,7 +282,6 @@ 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;
@@ -317,8 +316,7 @@ bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t* ret_crc)
 
 	/* calculate crc to return */
 	if (ret_crc != NULL) {
-		init_crc32_table(crc32_table);
-		*ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size);
+		*ret_crc = crc32(UBI_CRC32_INIT, buf, size);
 	}
 
 	/* transfer to hashmap */
@@ -442,7 +440,6 @@ 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;
@@ -458,8 +455,7 @@ bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc)
 
 	/* calculate crc to return */
 	if (ret_crc != NULL) {
-		init_crc32_table(crc32_table);
-		*ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size);
+		*ret_crc = crc32(UBI_CRC32_INIT, buf, size);
 	}
 
 	if (fwrite(buf, size, 1, fp) != 1) {
diff --git a/ubi-utils/src/common.h b/ubi-utils/src/common.h
index b27f866..89094ab 100644
--- a/ubi-utils/src/common.h
+++ b/ubi-utils/src/common.h
@@ -24,6 +24,7 @@ extern "C" {
 #endif
 
 #define MIN(a ,b) ((a) < (b) ? (a) : (b))
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 /* Error messages */
 #define errmsg(fmt, ...) do {                                             \
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/libpfi.c b/ubi-utils/src/libpfi.c
new file mode 100644
index 0000000..6de24ea
--- /dev/null
+++ b/ubi-utils/src/libpfi.c
@@ -0,0 +1,628 @@
+/*
+ * 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.
+ */
+
+/*
+ * A library to work with pfi files.
+ *
+ * Authors Oliver Lohmann
+ *         Andreas Arnez
+ *         Joern Engel
+ *         Frank Haverkamp
+ *         Artem Bityutskiy
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <mtd/ubi-header.h>
+#include <libpfi.h>
+#include "common.h"
+#include "bootenv.h"
+
+#define PROGRAM_NAME "libpfi"
+
+#define PFI_MAGIC     "PFI!\n"
+#define PFI_MAGIC_LEN (sizeof(PFI_MAGIC) - 1)
+#define PFI_DATA      "DATA\n"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#define PFI_MANDATORY     0x0001
+#define PFI_STRING        0x0002
+#define PFI_LISTVALUE     0x0004
+#define PFI_MANDATORY_UBI 0x0008
+
+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,
+	num_keys,
+};
+
+struct pfi_header {
+	uint8_t 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];
+};
+
+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 },
+};
+
+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[] = {"ubi"};
+
+/* 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))
+
+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 (struct 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 { /* 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 (struct pfi_header **head)
+{
+	int i;
+	struct pfi_header *self = 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 (struct pfi_header **head)
+{
+	int i;
+	struct 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 (struct 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 (struct 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 (struct 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 (struct 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_read(FILE *in, struct pfi_header *head)
+{
+	char mode[PFI_KEYWORD_LEN];
+	char buf[256];
+
+	if (fread(buf, 1, PFI_MAGIC_LEN, in) != PFI_MAGIC_LEN) {
+		errmsg("cannot read %d bytes", PFI_MAGIC_LEN);
+		perror("fread");
+		return -1;
+	}
+
+	if (memcmp(buf, PFI_MAGIC, PFI_MAGIC_LEN) != 0)  {
+		if (memcmp(buf, PFI_DATA, PFI_MAGIC_LEN) == 0)
+			return 1;
+
+		errmsg("PFI magic \"%s\" not found", PFI_MAGIC);
+		return -1;
+	}
+
+	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
+read_pfi_ubi(struct pfi_header *pfi_hd, struct pfi_ubi **pfi_ubi,
+	     const char *label)
+{
+	int err = 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;
+	struct pfi_ubi *res;
+	uint32_t i;
+	size_t size;
+
+	res = (struct pfi_ubi *) calloc(1, sizeof(struct pfi_ubi));
+	if (!res)
+		return -ENOMEM;
+
+	err = pfi_header_getnumber(pfi_hd, "size", &(res->data_size));
+	if (err != 0) {
+		errmsg("cannot read 'size' from PFI.");
+		goto err;
+	}
+
+	err = pfi_header_getnumber(pfi_hd, "crc", &(res->crc));
+	if (err != 0) {
+		errmsg("cannot read 'crc' from PFI.");
+		goto err;
+	}
+
+	err = pfi_header_getstring(pfi_hd, "ubi_ids", tmp_str, PFI_KEYWORD_LEN);
+	if (err != 0) {
+		errmsg("cannot read 'ubi_ids' from PFI.");
+		goto err;
+	}
+
+	err = bootenv_list_create(&ubi_id_list);
+	if (err != 0) {
+		goto err;
+	}
+	err = bootenv_list_create(&ubi_name_list);
+	if (err != 0) {
+		goto err;
+	}
+
+	err = bootenv_list_import(ubi_id_list, tmp_str);
+	if (err != 0) {
+		errmsg("cannot translate PFI value: %s", tmp_str);
+		goto err;
+	}
+
+	err = bootenv_list_to_num_vector(ubi_id_list, &size,
+					&(res->ids));
+	res->ids_size = size;
+	if (err != 0) {
+		errmsg("cannot create numeric value array: %s", tmp_str);
+		goto err;
+	}
+
+	if (res->ids_size == 0) {
+		err = -1;
+		errmsg("sanity check failed: No ubi_ids specified.");
+		goto err;
+	}
+
+	err = pfi_header_getstring(pfi_hd, "ubi_type",
+				  tmp_str, PFI_KEYWORD_LEN);
+	if (err != 0) {
+		errmsg("cannot read 'ubi_type' from PFI.");
+		goto err;
+	}
+	if (strcmp(tmp_str, "static") == 0)
+		res->vol_type = UBI_VID_STATIC;
+	else if (strcmp(tmp_str, "dynamic") == 0)
+		res->vol_type = UBI_VID_DYNAMIC;
+	else {
+		errmsg("unknown ubi_type in PFI.");
+		goto err;
+	}
+
+	err = pfi_header_getnumber(pfi_hd, "ubi_alignment", &(res->alignment));
+	if (err != 0) {
+		errmsg("cannot read 'ubi_alignment' from PFI.");
+		goto err;
+	}
+
+	err = pfi_header_getnumber(pfi_hd, "ubi_size", &(res->size));
+	if (err != 0) {
+		errmsg("cannot read 'ubi_size' from PFI.");
+		goto err;
+	}
+
+	err = pfi_header_getstring(pfi_hd, "ubi_names",
+				  tmp_str, PFI_KEYWORD_LEN);
+	if (err != 0) {
+		errmsg("cannot read 'ubi_names' from PFI.");
+		goto err;
+	}
+
+	err = bootenv_list_import(ubi_name_list, tmp_str);
+	if (err != 0) {
+		errmsg("cannot translate PFI value: %s", tmp_str);
+		goto err;
+	}
+	err = bootenv_list_to_vector(ubi_name_list, &size,
+				    &(tmp_names));
+	res->names_size = size;
+	if (err != 0) {
+		errmsg("cannot create string array: %s", tmp_str);
+		goto err;
+	}
+
+	if (res->names_size != res->ids_size) {
+		errmsg("sanity check failed: ubi_ids list does not match "
+			 "sizeof ubi_names list.");
+		err = -1;
+	}
+
+	/* copy tmp_names to own structure */
+	res->names = 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 err;
+}
+
+int
+free_pfi_ubi(struct pfi_ubi **pfi_ubi)
+{
+	size_t i;
+	struct pfi_ubi *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(struct list_entry **ubi_list, FILE *fp_pfi)
+{
+	int err = 0;
+	long long data_offs = 0;
+	long fpos;
+	char mode[PFI_KEYWORD_LEN];
+	char label[PFI_LABEL_LEN];
+	struct list_entry *tmp;
+
+	*ubi_list = list_empty(); struct pfi_ubi *ubi = NULL;
+	struct pfi_header *pfi_header = NULL;
+
+	/* read all headers from PFI and store them in lists */
+	err = pfi_header_init(&pfi_header);
+	if (err != 0) {
+		errmsg("cannot initialize pfi header.");
+		goto err;
+	}
+	while ((err == 0) && !feof(fp_pfi)) {
+		err = pfi_header_read(fp_pfi, pfi_header);
+		if (err != 0) {
+			if (err == 1) {
+				err = 0;
+				break; /* data section starts,
+					  all headers read */
+			}
+			else {
+				goto err;
+			}
+		}
+		err = pfi_header_getstring(pfi_header, "label", label,
+					  PFI_LABEL_LEN);
+		if (err != 0) {
+			errmsg("cannot read 'label' from PFI.");
+			goto err;
+		}
+		err = pfi_header_getstring(pfi_header, "mode", mode,
+					  PFI_KEYWORD_LEN);
+		if (err != 0) {
+			errmsg("cannot read 'mode' from PFI.");
+			goto err;
+		}
+		if (strcmp(mode, "ubi") == 0) {
+			err = read_pfi_ubi(pfi_header, &ubi, label);
+			if (err != 0) {
+				goto err;
+			}
+			*ubi_list = append_elem(ubi, *ubi_list);
+		}
+		else {
+			errmsg("recvieved unknown mode from PFI: %s", mode);
+			goto err;
+		}
+		ubi->data_offs = data_offs;
+		data_offs += ubi->data_size;
+	}
+
+	fpos = ftell(fp_pfi);
+	if (fpos == -1) {
+		errmsg("ftell returned error");
+		perror("ftell");
+		goto err;
+	}
+
+	list_for_each(ubi, tmp, *ubi_list)
+		ubi->data_offs += fpos;
+
+	goto out;
+
+ err:
+	*ubi_list = remove_all((free_func_t)&free_pfi_ubi, *ubi_list);
+ out:
+	pfi_header_destroy(&pfi_header);
+	return err;
+
+}
diff --git a/ubi-utils/src/libubigen.c b/ubi-utils/src/libubigen.c
index 6aef291..c3a0f9c 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,473 +15,297 @@
  * 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-header.h>
 
-#include "config.h"
-#include "ubigen.h"
+#include <mtd/ubi-header.h>
+#include <libubigen.h>
 #include "crc32.h"
+#include "common.h"
 
-#define UBI_NAME_SIZE		256
-#define DEFAULT_VID_OFFSET	((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE))
-#define MIN(a,b)		((a) < (b) ? (a) : (b))
-
-static uint32_t crc32_table[256];
-
-struct ubi_info {
-	struct ubi_vid_hdr* v;	/* Volume ID header */
-	struct ubi_ec_hdr* ec;	/* Erase count header */
-
-	FILE* fp_in;		/* Input Stream */
-	FILE* fp_out;		/* Output stream */
-
-	size_t peb_size;	/* Physical EB size in bytes */
-	size_t leb_size;	/* Size of a logical EB in a physical EB */
-	size_t leb_total;	/* Total input size in logical EB */
-	size_t alignment;	/* Block alignment */
-	size_t data_pad;	/* Size of padding in each physical EB */
-
-	size_t bytes_total;	/* Total input size in bytes */
-	size_t bytes_read;	/* Nymber of read bytes (total) */
-
-	uint32_t blks_written;	/* Number of written logical EB */
-
-	uint8_t* buf;		/* Allocated buffer */
-	uint8_t* ptr_ec_hdr;	/* Pointer to EC hdr in buf */
-	uint8_t* ptr_vid_hdr;	/* Pointer to VID hdr in buf */
-	uint8_t* ptr_data;	/* Pointer to data region in buf */
-};
-
-
-static uint32_t
-byte_to_blk(uint64_t byte, uint32_t peb_size)
-{
-	return (byte % peb_size) == 0
-		? (byte / peb_size)
-		: (byte / peb_size) + 1;
-}
+#define PROGRAM_NAME "libubigen"
 
-static int
-validate_ubi_info(ubi_info_t u)
-{
-	if ((u->v->vol_type != UBI_VID_DYNAMIC) &&
-	    (u->v->vol_type != UBI_VID_STATIC)) {
-		return EUBIGEN_INVALID_TYPE;
-	}
-
-	if (__be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) {
-		return EUBIGEN_INVALID_HDR_OFFSET;
-	}
-
-	return 0;
-}
-
-static int
-skip_blks(ubi_info_t u, uint32_t blks)
-{
-	uint32_t i;
-	size_t read = 0, to_read = 0;
-
-	/* Step to a maximum of leb_total - 1 to keep the
-	   restrictions. */
-	for (i = 0; i < MIN(blks, u->leb_total-1); i++) {
-		/* Read in data */
-		to_read = MIN(u->leb_size,
-			      (u->bytes_total - u->bytes_read));
-		read = fread(u->ptr_data, 1, to_read, u->fp_in);
-		if (read != to_read) {
-			return -EIO;
-		}
-		u->bytes_read += read;
-		u->blks_written++;
-	}
-
-	return 0;
-}
-
-static void
-clear_buf(ubi_info_t u)
-{
-	memset(u->buf, 0xff, u->peb_size);
-}
-
-static void
-write_ec_hdr(ubi_info_t u)
+/**
+ * ubigen_create_empty_vtbl - creates empty volume table.
+ * @size: physical eraseblock size on input, size of the volume table on output
+ *
+ * This function creates an empty volume table and returns a pointer to it in
+ * case of success and %NULL in case of failure. The volume table size is
+ * returned in @size which has to contain PEB size on input.
+ */
+struct ubi_vtbl_record *ubigen_create_empty_vtbl(int *size)
 {
-	memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE);
-}
+	struct ubi_vtbl_record *vtbl;
+	int i;
 
-static int
-fill_data_buffer_from_file(ubi_info_t u, size_t* read)
-{
-	size_t to_read = 0;
+	if (*size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE)
+		*size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
 
-	if (u-> fp_in == NULL)
-		return -EIO;
+	vtbl = calloc(1, *size);
+	if (!vtbl)
+		return NULL;
 
-	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;
+	for (i = 0; i < UBI_MAX_VOLUMES; i++) {
+		uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i],
+				     UBI_VTBL_RECORD_SIZE_CRC);
+		vtbl[i].crc = __cpu_to_be32(crc);
 	}
-	return 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);
-	}
+	return vtbl;
 }
 
-static void
-write_vid_hdr(ubi_info_t u, ubigen_action_t action)
+/**
+ * ubigen_info_init - initialize libubigen.
+ * @ui: libubigen information
+ * @peb_size: flash physical eraseblock size
+ * @min_io_size: flash minimum input/output unit size
+ * @subpage_size: flash sub-page, if present (has to be equivalent to
+ *                @min_io_size if does not exist)
+ * @vid_hdr_offs: offset of the VID header
+ * @ubi_ver: UBI version
+ * @ec: initial erase counter
+ */
+void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
+		      int subpage_size, int vid_hdr_offs, int ubi_ver,
+		      long long ec)
 {
-	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);
+	if (!vid_hdr_offs)
+		vid_hdr_offs = subpage_size;
+
+	ui->peb_size = peb_size;
+	ui->min_io_size = min_io_size;
+	ui->vid_hdr_offs = vid_hdr_offs;
+	ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1;
+	ui->data_offs /= min_io_size;
+	ui->data_offs *= min_io_size;
+	ui->leb_size = peb_size - ui->data_offs;
+	ui->ubi_ver = ubi_ver;
+	ui->ec = ec;
 }
 
-static int
-write_to_output_stream(ubi_info_t u)
+/**
+ * ubigen_add_volume - add a volume to the volume table.
+ * @vol_id: volume ID
+ * @bytes: volume size in bytes
+ * @alignment: volume alignment
+ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ * @name: volume name
+ * @ui: libubigen information
+ * @vtbl: volume table to add to
+ *
+ * This function adds volume described by input parameters to the volume table
+ * @vtbl.
+ */
+void ubigen_add_volume(const struct ubigen_info *ui,
+		       const struct ubigen_vol_info *vi,
+		       struct ubi_vtbl_record *vtbl)
 {
-	size_t written;
-
-	written = fwrite(u->buf, 1, u->peb_size, u->fp_out);
-	if (written != u->peb_size) {
-		return -EIO;
-	}
-	return 0;
+	struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
+	uint32_t tmp;
+
+	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);
+
+	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);
 }
 
-int
-ubigen_write_leb(ubi_info_t u, ubigen_action_t action)
+/**
+ * init_ec_hdr - initialize EC header.
+ * @ui: libubigen information
+ * @hdr: the EC header to initialize
+ */
+static void init_ec_hdr(const struct ubigen_info *ui,
+		        struct ubi_ec_hdr *hdr)
 {
-	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);
-	}
+	uint32_t crc;
 
-	u->v->lnum = __cpu_to_be32(u->blks_written);
+	memset(hdr, '\0', sizeof(struct ubi_ec_hdr));
 
-	if (action & MARK_AS_UPDATE) {
-		u->v->copy_flag = (u->v->copy_flag)++;
-	}
+	hdr->magic = __cpu_to_be32(UBI_EC_HDR_MAGIC);
+	hdr->version = ui->ubi_ver;
+	hdr->ec = __cpu_to_be64(ui->ec);
+	hdr->vid_hdr_offset = __cpu_to_be32(ui->vid_hdr_offs);
 
-	write_vid_hdr(u, action);
-	rc = write_to_output_stream(u);
-	if (rc != 0)
-		return rc;
+	hdr->data_offset = __cpu_to_be32(ui->data_offs);
 
-	/* Update current handle */
-	u->bytes_read += read;
-	u->blks_written++;
-	return 0;
+	crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	hdr->hdr_crc = __cpu_to_be32(crc);
 }
 
-int
-ubigen_write_complete(ubi_info_t u)
+/**
+ * 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)
 {
-	size_t i;
-	int rc = 0;
+	uint32_t crc;
 
-	for (i = 0; i < u->leb_total; i++) {
-		rc = ubigen_write_leb(u,  NO_ERROR);
-		if (rc != 0)
-			return rc;
+	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);
 	}
 
-	return 0;
+	crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
+	hdr->hdr_crc = __cpu_to_be32(crc);
 }
 
-int
-ubigen_write_broken_update(ubi_info_t u, uint32_t blk)
+/**
+ * ubigen_write_volume - write UBI volume.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @bytes: volume size in bytes
+ * @in: input file descriptor (has to be properly seeked)
+ * @out: output file descriptor
+ *
+ * This function reads the contents of the volume from the input file @in and
+ * writes the UBI volume to the output file @out. Returns zero on success and
+ * %-1 on failure.
+ */
+int ubigen_write_volume(const struct ubigen_info *ui,
+			const struct ubigen_vol_info *vi,
+			long long bytes, FILE *in, FILE *out)
 {
-	int 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;
-}
+	int len = vi->usable_leb_size, rd, lnum = 0;
+	char inbuf[ui->leb_size], outbuf[ui->peb_size];
+
+	memset(outbuf, 0xFF, ui->data_offs);
+	init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf);
+
+	while (bytes) {
+		int l;
+		struct ubi_vid_hdr *vid_hdr;
+
+		if (bytes < len)
+			len = bytes;
+		bytes -= len;
+
+		l = len;
+		do {
+			rd = fread(inbuf + len - l, 1, l, in);
+			if (rd == 0) {
+				if (ferror(in))
+					errmsg("cannot read %d bytes from the input"
+					       " file", l);
+				else
+					errmsg("not enough data in the input file");
+				return -1;
+			}
+
+			l -= rd;
+		} while (l);
+
+		vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+		init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
+
+		memcpy(outbuf + ui->data_offs, inbuf, len);
+		memset(outbuf + ui->data_offs + len, 0xFF,
+		       ui->peb_size - ui->data_offs - len);
+
+		if (fwrite(outbuf, 1, ui->peb_size, out) != ui->peb_size) {
+			errmsg("cannot write %d bytes from the output"
+			       " file", l);
+			return -1;
+		}
 
-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;
+		lnum += 1;
 	}
-	if (err) return;
-
-	fprintf(stderr, "ubi volume\n");
-	fprintf(stderr, "version      :	  %8d\n", u->v->version);
-	fprintf(stderr, "vol_id	      :	  %8d\n", __be32_to_cpu(u->v->vol_id));
-	fprintf(stderr, "vol_type     :	  %8s\n",
-		u->v->vol_type == UBI_VID_STATIC ?
-		"static" : "dynamic");
-	fprintf(stderr, "used_ebs     :	  %8d\n",
-		__be32_to_cpu(u->v->used_ebs));
-	fprintf(stderr, "peb_size     : 0x%08x\n", u->peb_size);
-	fprintf(stderr, "leb_size     : 0x%08x\n", u->leb_size);
-	fprintf(stderr, "data_pad     : 0x%08x\n",
-		__be32_to_cpu(u->v->data_pad));
-	fprintf(stderr, "leb_total    :	  %8d\n", u->leb_total);
-	fprintf(stderr, "header offs  : 0x%08x\n",
-		__be32_to_cpu(u->ec->vid_hdr_offset));
-	fprintf(stderr, "bytes_total  :	  %8d\n", u->bytes_total);
-	fprintf(stderr, "  +  in MiB  : %8.2f M\n",
-		((float)(u->bytes_total)) / 1024 / 1024);
-	fprintf(stderr, "-------------------------------\n\n");
-#else
-	return;
-#endif
-}
 
-int
-ubigen_destroy(ubi_info_t *u)
-{
-	if (u == NULL)
-		return -EINVAL;
-
-	ubi_info_t tmp = *u;
-
-	if (tmp) {
-		if (tmp->v)
-			free(tmp->v);
-		if (tmp->ec)
-			free(tmp->ec);
-		if (tmp->buf)
-			free(tmp->buf);
-		free(tmp);
-	}
-	*u = NULL;
 	return 0;
 }
 
-void
-ubigen_init(void)
-{
-	init_crc32_table(crc32_table);
-}
-
-int
-ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type,
-	      uint32_t peb_size, uint64_t ec, uint32_t alignment,
-	      uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag,
-	      size_t data_size, FILE* fp_in, FILE* fp_out)
+/**
+ * ubigen_write_layout_vol - write UBI layout volume
+ * @ui: libubigen information
+ * @vtbl: volume table
+ * @out: output file stream
+ *
+ * This function creates the UBI layout volume which contains 2 copies of the
+ * volume table. Returns zero in case of success and %-1 in case of failure.
+ */
+int ubigen_write_layout_vol(const struct ubigen_info *ui,
+			    struct ubi_vtbl_record *vtbl, FILE *out)
 {
-	int rc = 0;
-	ubi_info_t res = NULL;
-	uint32_t crc;
-	uint32_t data_offset;
-
-	if (alignment == 0) {
-		rc = EUBIGEN_INVALID_ALIGNMENT;
-		goto ubigen_create_err;
-	}
-	if ((fp_in == NULL) || (fp_out == NULL)) {
-		rc = -EINVAL;
-		goto ubigen_create_err;
-	}
-
-	res = (ubi_info_t) calloc(1, sizeof(struct ubi_info));
-	if (res == NULL) {
-		rc = -ENOMEM;
-		goto ubigen_create_err;
-	}
-
-	res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr));
-	if (res->v == NULL) {
-		rc = -ENOMEM;
-		goto ubigen_create_err;
-	}
-
-	res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr));
-	if (res->ec == NULL) {
-		rc = -ENOMEM;
-		goto ubigen_create_err;
-	}
-
-	/* data which is needed in the general process */
-	vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET;
-	data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE;
-	res->bytes_total = data_size;
-	res->peb_size = peb_size ? peb_size : DEFAULT_BLOCKSIZE;
-	res->data_pad = (res->peb_size - data_offset) % alignment;
-	res->leb_size = res->peb_size - data_offset - res->data_pad;
-	res->leb_total = byte_to_blk(data_size, res->leb_size);
-	res->alignment = alignment;
-
-	if ((res->peb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) {
-		rc = EUBIGEN_TOO_SMALL_EB;
-		goto ubigen_create_err;
-	}
-	res->fp_in = fp_in;
-	res->fp_out = fp_out;
-
-	/* vid hdr data which doesn't change */
-	res->v->magic = __cpu_to_be32(UBI_VID_HDR_MAGIC);
-	res->v->version = version ? version : UBI_VERSION;
-	res->v->vol_type = vol_type;
-	res->v->vol_id = __cpu_to_be32(vol_id);
-	res->v->compat = compat_flag;
-	res->v->data_pad = __cpu_to_be32(res->data_pad);
-
-	/* static only: used_ebs */
-	if (res->v->vol_type == UBI_VID_STATIC) {
-		res->v->used_ebs = __cpu_to_be32(byte_to_blk
-						(res->bytes_total,
-						 res->leb_size));
-	}
-
-	/* ec hdr (fixed, doesn't change) */
-	res->ec->magic = __cpu_to_be32(UBI_EC_HDR_MAGIC);
-	res->ec->version = version ? version : UBI_VERSION;
-	res->ec->ec = __cpu_to_be64(ec);
-	res->ec->vid_hdr_offset = __cpu_to_be32(vid_hdr_offset);
-
-	res->ec->data_offset = __cpu_to_be32(data_offset);
-
-	crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec,
-			UBI_EC_HDR_SIZE_CRC);
-	res->ec->hdr_crc = __cpu_to_be32(crc);
-
-	/* prepare a read buffer */
-	res->buf = (uint8_t*) malloc (res->peb_size * sizeof(uint8_t));
-	if (res->buf == NULL) {
-		rc = -ENOMEM;
-		goto ubigen_create_err;
-	}
-
-	/* point to distinct regions within the buffer */
-	res->ptr_ec_hdr = res->buf;
-	res->ptr_vid_hdr = res->buf + __be32_to_cpu(res->ec->vid_hdr_offset);
-	res->ptr_data = res->buf + __be32_to_cpu(res->ec->vid_hdr_offset)
-		+ UBI_VID_HDR_SIZE;
-
-	rc = validate_ubi_info(res);
-	if (rc != 0) {
-		fprintf(stderr, "Volume validation failed: %d\n", rc);
-		goto ubigen_create_err;
-	}
-
-	dump_info(res);
-	*u = res;
-	return rc;
-
-ubigen_create_err:
-	if (res) {
-		if (res->v)
-			free(res->v);
-		if (res->ec)
-			free(res->ec);
-		if (res->buf)
-			free(res->buf);
-		free(res);
+	int size = ui->leb_size;
+	struct ubigen_vol_info vi;
+	char outbuf[ui->peb_size];
+	struct ubi_vid_hdr *vid_hdr;
+
+	if (size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE)
+		size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
+
+	vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
+	vi.id = UBI_LAYOUT_VOL_ID;
+	vi.alignment = 1;
+	vi.data_pad = 0;
+	vi.usable_leb_size = ui->leb_size;
+	vi.type = UBI_VID_DYNAMIC;
+	vi.name = UBI_LAYOUT_VOLUME_NAME;
+	vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
+	vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
+
+	memset(outbuf, 0xFF, ui->data_offs);
+	vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+	init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf);
+	memcpy(outbuf + ui->data_offs, vtbl, size);
+	memset(outbuf + ui->data_offs + size, 0xFF,
+	       ui->peb_size - ui->data_offs - size);
+
+	init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
+	size = fwrite(outbuf, 1, ui->peb_size, out);
+	if (size == ui->peb_size) {
+		init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
+		size = fwrite(outbuf, 1, ui->peb_size, out);
+		if (size != ui->peb_size) {
+			errmsg("cannot write %d bytes", ui->peb_size);
+			perror("write");
+			return -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)
-{
-	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/src/list.c b/ubi-utils/src/list.c
index 6eb716b..a701158 100644
--- a/ubi-utils/src/list.c
+++ b/ubi-utils/src/list.c
@@ -24,36 +24,30 @@
 
 #include "list.h"
 
-list_t
-mk_empty(void)
-{
-	return (list_t) NULL;
-}
-
 int
-is_empty(list_t l)
+is_empty(struct list_entry *l)
 {
 	return l == NULL;
 }
 
 info_t
-head(list_t l)
+head(struct list_entry *l)
 {
 	assert(!is_empty(l));
 	return l->info;
 }
 
-list_t
-tail(list_t l)
+struct list_entry *
+tail(struct list_entry *l)
 {
 	assert(!is_empty(l));
 	return l->next;
 }
 
-list_t
-remove_head(list_t l)
+struct list_entry *
+remove_head(struct list_entry *l)
 {
-	list_t res;
+	struct list_entry *res;
 	assert(!is_empty(l));
 
 	res = l->next;
@@ -61,10 +55,10 @@ remove_head(list_t l)
 	return res;
 }
 
-list_t
-cons(info_t e, list_t l)
+struct list_entry *
+cons(info_t e, struct list_entry *l)
 {
-	list_t res = malloc(sizeof(*l));
+	struct list_entry *res = malloc(sizeof(*l));
 	if (!res)
 		return NULL;
 	res->info = e;
@@ -73,14 +67,14 @@ cons(info_t e, list_t l)
 	return res;
 }
 
-list_t
-prepend_elem(info_t e, list_t l)
+struct list_entry *
+prepend_elem(info_t e, struct list_entry *l)
 {
 	return cons(e,l);
 }
 
-list_t
-append_elem(info_t e, list_t l)
+struct list_entry *
+append_elem(info_t e, struct list_entry *l)
 {
 	if (is_empty(l)) {
 		return cons(e,l);
@@ -90,8 +84,8 @@ append_elem(info_t e, list_t l)
 	return l;
 }
 
-list_t
-insert_sorted(cmp_func_t cmp, info_t e, list_t l)
+struct list_entry *
+insert_sorted(cmp_func_t cmp, info_t e, struct list_entry *l)
 {
 	if (is_empty(l))
 		return cons(e, l);
@@ -112,12 +106,12 @@ insert_sorted(cmp_func_t cmp, info_t e, list_t l)
 	return NULL;
 }
 
-list_t
-remove_all(free_func_t free_func, list_t l)
+struct list_entry *
+remove_all(free_func_t free_func, struct list_entry *l)
 {
 	if (is_empty(l))
 		return l;
-	list_t lnext = l->next;
+	struct list_entry *lnext = l->next;
 
 	if (free_func && l->info) {
 		free_func(&(l->info));
@@ -129,7 +123,7 @@ remove_all(free_func_t free_func, list_t l)
 
 
 info_t
-is_in(cmp_func_t cmp, info_t e, list_t l)
+is_in(cmp_func_t cmp, info_t e, struct list_entry *l)
 {
 	return
 	(is_empty(l))
@@ -139,11 +133,11 @@ is_in(cmp_func_t cmp, info_t e, list_t l)
 
 
 void
-apply(process_func_t process_func, list_t l)
+apply(process_func_t process_func, struct list_entry *l)
 {
-	list_t ptr;
+	struct list_entry *ptr;
 	void *i;
-	foreach(i, ptr, l) {
+	list_for_each(i, ptr, l) {
 		process_func(i);
 	}
 }
diff --git a/ubi-utils/src/list.h b/ubi-utils/src/list.h
index e8452a2..58bfe7e 100644
--- a/ubi-utils/src/list.h
+++ b/ubi-utils/src/list.h
@@ -1,5 +1,3 @@
-#ifndef __LIST_H__
-#define __LIST_H__
 /*
  * Copyright (c) International Business Machines Corp., 2006
  *
@@ -20,37 +18,44 @@
  * Author: Oliver Lohmann
  */
 
+#ifndef __UBIUTILS_LIST_H__
+#define __UBIUTILS_LIST_H__
+
 #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)
+#define list_for_each(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)
+
+static inline struct list_entry *list_empty(void)
+{
+	return 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;
+struct list_entry {
+	struct list_entry *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__ */
+struct list_entry *list_empty(void);
+int    is_empty(struct list_entry *l);
+info_t is_in(cmp_func_t cmp, info_t e, struct list_entry *l);
+info_t head(struct list_entry *l);
+struct list_entry *tail(struct list_entry *l);
+struct list_entry *remove_head(struct list_entry *l);
+struct list_entry *cons(info_t e, struct list_entry *l);
+struct list_entry *prepend_elem(info_t e, struct list_entry *);
+struct list_entry *append_elem(info_t e, struct list_entry *);
+struct list_entry *remove_all(free_func_t free_func, struct list_entry *l);
+struct list_entry *insert_sorted(cmp_func_t cmp_func, info_t e, struct list_entry *l);
+void   apply(process_func_t process_func, struct list_entry *l);
+
+#endif /* !__UBIUTILS_LIST_H__ */
diff --git a/ubi-utils/src/peb.c b/ubi-utils/src/peb.c
deleted file mode 100644
index 160a463..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 peb_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 = peb_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
index cacf33f..4289fca 100644
--- a/ubi-utils/src/pfi2bin.c
+++ b/ubi-utils/src/pfi2bin.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) International Business Machines Corp., 2006
- * Copyright (C) 2007 Nokia Corporation
+ * 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
@@ -30,29 +30,21 @@
  */
 
 #include <stdlib.h>
-#include <stdint.h>
 #include <getopt.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <errno.h>
+#include <unistd.h>
 
-#include <ubigen.h>
 #include <mtd/ubi-header.h>
+#include <libubigen.h>
+#include <libpfi.h>
 #include "common.h"
 #include "list.h"
-#include "reader.h"
-#include "peb.h"
-#include "crc32.h"
 
 #define PROGRAM_VERSION "1.5"
 #define PROGRAM_NAME    "pfi2bin"
 
-#define ERR_BUF_SIZE 1024
-
-static uint32_t crc32_table[256];
-static char err_buf[ERR_BUF_SIZE];
-
 static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
 " - a tool to convert PFI files into raw flash images. Note, if not\n"
 "sure about some of the parameters, do not specify them and let the utility to\n"
@@ -269,386 +261,110 @@ static int parse_opt(int argc, char * const argv[])
 	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.
+ * pfi2vol_info - convert PFI UBI volume information to libubigen.
+ * @pfi: PFI UBI volume information
+ * @n: PFI volume index to convert
+ * @vi: libubigen volume information
  */
-static int
-memorize_raw_eb(pfi_raw_t pfi_raw, list_t *raw_pebs)
-{
-	int err = 0;
-	int i, read, to_read, eb_num, bytes_left;
-	list_t pebs = *raw_pebs;
-	peb_t	peb  = NULL;
-
-	long old_file_pos = ftell(args.fp_in);
-	for (i = 0; i < (int)pfi_raw->starts_size; i++) {
-		bytes_left = pfi_raw->data_size;
-		err = fseek(args.fp_in, old_file_pos, SEEK_SET);
-		if (err != 0)
-			goto err;
-
-		eb_num = byte_to_blk(pfi_raw->starts[i], args.peb_size);
-		while (bytes_left) {
-			to_read = MIN(bytes_left, args.peb_size);
-			err = peb_new(eb_num++, args.peb_size, &peb);
-			if (err != 0)
-				goto err;
-			read = fread(peb->data, 1, to_read, args.fp_in);
-			if (read != to_read) {
-				err = -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 err;
-}
-
-static int
-convert_ubi_volume(pfi_ubi_t ubi, list_t raw_pebs,
-		struct ubi_vtbl_record *vol_tab,
-		size_t *ebs_written)
+static void pfi2vol_info(const struct pfi_ubi *pfi, int n,
+			 struct ubigen_vol_info *vi,
+			 const struct ubigen_info *ui)
 {
-	int err = 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;
-	}
-
-	err = peb_new(0, 0, &cmp_peb);
-	if (err != 0)
-		goto err;
-
-	long old_file_pos = ftell(args.fp_in);
-	for (i = 0; i < ubi->ids_size; i++) {
-		err = fseek(args.fp_in, old_file_pos, SEEK_SET);
-		if (err != 0)
-			goto err;
-		err = ubigen_create(&u, ubi->ids[i], vol_type,
-				   args.peb_size, args.ec,
-				   ubi->alignment, args.ubi_ver,
-				   args.vid_hdr_offs, 0, ubi->data_size,
-				   args.fp_in, args.fp_out);
-		if (err != 0)
-			goto err;
-
-		err = ubigen_get_leb_total(u, &leb_total);
-		if (err != 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) {
-				err = peb_write(args.fp_out, raw_peb);
-			}
-			else {
-				err = ubigen_write_leb(u, NO_ERROR);
-				j++;
-			}
-			if (err != 0)
-				goto err;
-			(*ebs_written)++;
-		}
-		/* memorize volume table entry */
-		err = ubigen_set_lvol_rec(u, ubi->size,
-				ubi->names[i],
-				(void*) &vol_tab[ubi->ids[i]]);
-		if (err != 0)
-			goto err;
-		ubigen_destroy(&u);
+	vi->id = pfi->ids[n];
+	vi->bytes = pfi->size;
+	vi->alignment = pfi->alignment;
+	vi->data_pad = ui->leb_size % vi->alignment;
+	vi->usable_leb_size = ui->leb_size - vi->data_pad;
+	vi->type = pfi->vol_type;
+	vi->name = pfi->names[n];
+	vi->name_len = strlen(vi->name);
+	if (vi->name_len > UBI_VOL_NAME_MAX) {
+		errmsg("too long name, cut to %d symbols: \"%s\"",
+		       UBI_VOL_NAME_MAX, vi->name);
+		vi->name_len = UBI_VOL_NAME_MAX;
 	}
 
-	peb_free(&cmp_peb);
-	return 0;
-
-err:
-	peb_free(&cmp_peb);
-	ubigen_destroy(&u);
-	return err;
-}
-
-
-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;
+	vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size;
+	vi->compat = 0;
 }
 
-/**
- * @brief		Builds a UBI volume table from a volume entry list.
- * @return 0		On success.
- *	   else		Error.
- */
-static int
-write_ubi_volume_table(list_t raw_pebs,
-		struct ubi_vtbl_record *vol_tab, size_t vol_tab_size,
-		size_t *ebs_written)
+static int create_flash_image(void)
 {
-	int err = 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;
-
-	err = peb_new(0, 0, &cmp_peb);
-	if (err != 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.
-	 */
-	err = ubigen_create(&u, UBI_LAYOUT_VOL_ID, UBI_VID_DYNAMIC,
-			   args.peb_size, args.ec,
-			   1, args.ubi_ver,
-			   args.vid_hdr_offs, UBI_COMPAT_REJECT,
-			   vol_tab_size, stdin, args.fp_out);
-			   /* @FIXME stdin for fp_in is a hack */
-	if (err != 0)
-		goto err;
-	err = ubigen_get_leb_size(u, &leb_size);
-	if (err != 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");
-
-	err = ubigen_create(&u, UBI_LAYOUT_VOL_ID, UBI_VID_DYNAMIC,
-			   args.peb_size, args.ec,
-			   1, args.ubi_ver, args.vid_hdr_offs,
-			   UBI_COMPAT_REJECT, leb_size * UBI_LAYOUT_VOLUME_EBS,
-			   fp_leb, args.fp_out);
-	if (err != 0)
-		goto err;
-	err = ubigen_get_leb_total(u, &leb_total);
-	if (err != 0)
-		goto err;
-
-	long old_file_pos = ftell(fp_leb);
-	while(j < leb_total) {
-		err = fseek(fp_leb, old_file_pos, SEEK_SET);
-		if (err != 0)
-			goto err;
-
-		cmp_peb->num = *ebs_written;
-		raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb,
-				raw_pebs);
-		if (raw_peb) {
-			err = peb_write(args.fp_out, raw_peb);
-		}
-		else {
-			err = ubigen_write_leb(u, NO_ERROR);
-			j++;
-		}
-
-		if (err != 0)
-			goto err;
-		(*ebs_written)++;
-	}
-
-err:
-	free(ptr);
-	peb_free(&cmp_peb);
-	ubigen_destroy(&u);
-	fclose(fp_leb);
-	return err;
-}
-
-static int
-write_remaining_raw_ebs(list_t raw_blocks, size_t *ebs_written,
-			FILE* fp_out)
-{
-	int err = 0;
-	uint32_t j, delta;
-	list_t ptr;
-	peb_t empty_eb, peb;
-
-	/* create an empty 0xff EB (for padding) */
-	err = peb_new(0, args.peb_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) {
-			errmsg("eb_num: %d\n", peb->num);
-			errmsg("Bug: This should never happen. %d %s",
-				__LINE__, __FILE__);
-			goto err;
-		}
-
-		delta = peb->num - *ebs_written;
-		for (j = 0; j < delta; j++) {
-			err = peb_write(fp_out, empty_eb);
-			if (err != 0)
-				goto err;
-			(*ebs_written)++;
-		}
-		err = peb_write(fp_out, peb);
-		if (err != 0)
-			goto err;
-		(*ebs_written)++;
+	int i, err, vtbl_size = args.peb_size;
+	struct ubigen_info ui;
+	struct list_entry *ubi_list = list_empty(), *ptr;
+	struct ubi_vtbl_record *vtbl;
+	struct pfi_ubi *pfi;
+
+	vtbl = ubigen_create_empty_vtbl(&vtbl_size);
+	if (!vtbl) {
+		errmsg("cannot initialize volume table");
+		return -1;
 	}
 
-err:
-	peb_free(&empty_eb);
-	return err;
-}
-
-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;
+	ubigen_info_init(&ui, args.peb_size, args.min_io_size,
+			 args.subpage_size, args.vid_hdr_offs, args.ubi_ver,
+			 args.ec);
 
-	res = (struct ubi_vtbl_record*) calloc(1, *vol_tab_size);
-	if (vol_tab == NULL) {
-		return -ENOMEM;
+	err = read_pfi_headers(&ubi_list, args.fp_in);
+	if (err != 0) {
+		errmsg("cannot read PFI headers, error %d", err);
+		goto error;
 	}
 
-	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);
-	}
+	/* Add all volumes to the volume table */
+	list_for_each(pfi, ptr, ubi_list)
+		for (i = 0; i < pfi->ids_size; i++) {
+			struct ubigen_vol_info vi;
 
-	*vol_tab = res;
-	return 0;
-}
-
-static int
-create_raw(void)
-{
-	int err = 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;
+			pfi2vol_info(pfi, i, &vi, &ui);
+			ubigen_add_volume(&ui, &vi, vtbl);
+		}
 
-	err = init_vol_tab (&vol_tab, &vol_tab_size);
-	if (err != 0) {
-		errmsg("cannot initialize volume table");
-		goto err;
+	err = ubigen_write_layout_vol(&ui, vtbl, args.fp_out);
+	if (err) {
+		errmsg("cannot create layout volume");
+		goto error;
 	}
 
-	err = read_pfi_headers(&pfi_raws, &pfi_ubis, args.fp_in,
-			err_buf, ERR_BUF_SIZE);
-	if (err != 0) {
-		errmsg("cannot read pfi header: %s err: %d", err_buf, err);
-		goto err;
-	}
+	/* Write all volumes */
+	list_for_each(pfi, ptr, ubi_list)
+		for (i = 0; i < pfi->ids_size; i++) {
+			struct ubigen_vol_info vi;
+
+			pfi2vol_info(pfi, i, &vi, &ui);
+			err = fseek(args.fp_in, pfi->data_offs, SEEK_SET);
+			if (err == -1) {
+				errmsg("cannot seek input file");
+				perror("fseek");
+				goto error;
+			}
 
-	pfi_raw_t pfi_raw;
-	foreach(pfi_raw, ptr, pfi_raws) {
-		err = memorize_raw_eb(pfi_raw, &raw_pebs);
-		if (err != 0) {
-			errmsg("cannot create raw_block in mem. err: %d\n", err);
-			goto err;
+			err = ubigen_write_volume(&ui, &vi, pfi->data_size,
+						  args.fp_in, args.fp_out);
+			if (err) {
+				errmsg("cannot write volume %d", vi.id);
+				goto error;
+			}
 		}
-	}
 
-	pfi_ubi_t pfi_ubi;
-	foreach(pfi_ubi, ptr, pfi_ubis) {
-		err = convert_ubi_volume(pfi_ubi, raw_pebs,
-					vol_tab, &ebs_written);
-		if (err != 0) {
-			errmsg("cannot convert UBI volume. err: %d\n", err);
-			goto err;
+	if (args.fp_out != stdout) {
+		i = ftell(args.fp_out);
+		if (i == -1) {
+			errmsg("cannot seek output file");
+			perror("ftell");
+			goto error;
 		}
-	}
 
-	err = write_ubi_volume_table(raw_pebs, vol_tab, vol_tab_size,
-			&ebs_written);
-	if (err != 0) {
-		errmsg("cannot write UBI volume table. err: %d\n", err);
-		goto err;
+		printf("physical eraseblocks written: %d (", i / ui.peb_size);
+		ubiutils_print_bytes(i, 0);
+		printf(")\n");
 	}
 
-	err  = write_remaining_raw_ebs(raw_pebs, &ebs_written, args.fp_out);
-	if (err != 0)
-		goto err;
-
-	if (args.fp_out != stdout)
-		printf("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);
+error:
+	free(vtbl);
+	ubi_list = remove_all((free_func_t)&free_pfi_ubi, ubi_list);
 	return err;
 }
 
@@ -660,17 +376,8 @@ int main(int argc, char * const argv[])
 	if (err)
 		return -1;
 
-	ubigen_init();
-	init_crc32_table(crc32_table);
-
-	err = create_raw();
-	if (err != 0) {
-		errmsg("creating RAW failed");
-		goto err;
-	}
-
-err:
-	if (err != 0)
+	err = create_flash_image();
+	if (err)
 		remove(args.f_out);
 
 	return err;
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/ubicrc32.c b/ubi-utils/src/ubicrc32.c
index 0f10b31..8064439 100644
--- a/ubi-utils/src/ubicrc32.c
+++ b/ubi-utils/src/ubicrc32.c
@@ -91,8 +91,7 @@ static int parse_opt(int argc, char * const argv[])
 int main(int argc, char * const argv[])
 {
 	int err = 0;
-	uint32_t crc32_table[256];
-	uint32_t crc32 = UBI_CRC32_INIT;
+	uint32_t crc = UBI_CRC32_INIT;
 	char buf[BUFSIZE];
 	FILE *fp;
 
@@ -110,8 +109,6 @@ int main(int argc, char * const argv[])
 	if (err)
 		return err;
 
-	init_crc32_table(crc32_table);
-
 	while (!feof(fp)) {
 		size_t read;
 
@@ -122,10 +119,10 @@ int main(int argc, char * const argv[])
 			err = -1;
 			goto out_close;
 		}
-		crc32 = clc_crc32(crc32_table, crc32, buf, read);
+		crc = crc32(crc, buf, read);
 	}
 
-	printf("0x%08x\n", crc32);
+	printf("0x%08x\n", crc);
 
 out_close:
 	if (fp != stdin)
diff --git a/ubi-utils/src/ubigen.h b/ubi-utils/src/ubigen.h
deleted file mode 100644
index bf4b384..0000000
--- a/ubi-utils/src/ubigen.h
+++ /dev/null
@@ -1,150 +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: Frank Haverkamp
- *
- * An utility to update UBI volumes.
- */
-
-#ifndef __UBIGEN_H__
-#define __UBIGEN_H__
-
-#include <stdio.h>
-#include <stdint.h>
-#include <mtd/ubi-header.h>
-#include <asm/byteorder.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/unubi.c b/ubi-utils/src/unubi.c
index 5c1d324..1d4b35b 100644
--- a/ubi-utils/src/unubi.c
+++ b/ubi-utils/src/unubi.c
@@ -121,8 +121,6 @@ static const char *usage =
 #define FN_VOLWH	"%s/volume%03u"			/* whole volume */
 #define FN_VITBL	"%s/vol_info_table%u"		/* vol info table */
 
-static uint32_t crc32_table[256];
-
 /* struct args:
  *	bsize		int, blocksize of image blocks
  *	hsize		int, eraseblock header size
@@ -351,7 +349,7 @@ data_crc(FILE* fpin, size_t length, uint32_t *ret_crc)
 	if (rc < 0)
 		return -1;
 
-	crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, length);
+	crc = crc32(UBI_CRC32_INIT, buf, length);
 	*ret_crc = crc;
 	return 0;
 }
@@ -462,8 +460,7 @@ extract_itable(FILE *fpin, struct eb_info *cur, size_t bsize, size_t num,
 		}
 
 		/* check crc */
-		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &rec,
-				UBI_VTBL_RECORD_SIZE_CRC);
+		crc = crc32(UBI_CRC32_INIT, &rec, UBI_VTBL_RECORD_SIZE_CRC);
 		if (crc != __be32_to_cpu(rec.crc))
 			continue;
 
@@ -689,8 +686,7 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
 		}
 
 		/* check erasecounter header crc */
-		crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->ec),
-				UBI_EC_HDR_SIZE_CRC);
+		crc = crc32(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;
@@ -734,8 +730,7 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
 		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);
+		crc = crc32(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;
@@ -932,7 +927,6 @@ main(int argc, char *argv[])
 	vols_len = 0;
 	vols = NULL;
 	fpin = NULL;
-	init_crc32_table(crc32_table);
 
 	/* setup struct args a */
 	memset(&a, 0, sizeof(a));
diff --git a/ubi-utils/src/unubi_analyze.c b/ubi-utils/src/unubi_analyze.c
index 2ab3b87..3f3a480 100644
--- a/ubi-utils/src/unubi_analyze.c
+++ b/ubi-utils/src/unubi_analyze.c
@@ -100,7 +100,7 @@ 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];
+	uint32_t crc;
 	uint64_t *erase_counts;
 	FILE* fpdata;
 	FILE* fpplot;
@@ -109,9 +109,6 @@ unubi_analyze_ec_hdr(struct eb_info *first, const char *path)
 	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);
@@ -164,8 +161,7 @@ unubi_analyze_ec_hdr(struct eb_info *first, const char *path)
 	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);
+		crc = crc32(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)))
-- 
cgit v1.2.3