]> www.infradead.org Git - mtd-utils.git/commitdiff
ubi-utils: massive changes
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Tue, 22 Jan 2008 14:02:52 +0000 (16:02 +0200)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Tue, 22 Jan 2008 14:22:52 +0000 (16:22 +0200)
This commit basically removes most of the old ubi utilities
as they are barely maintainamble.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
21 files changed:
ubi-utils/Makefile
ubi-utils/inc/libpfi.h [moved from ubi-utils/src/pfi.h with 86% similarity]
ubi-utils/inc/libubigen.h [new file with mode: 0644]
ubi-utils/src/bootenv.c
ubi-utils/src/common.h
ubi-utils/src/crc32.c
ubi-utils/src/crc32.h
ubi-utils/src/libpfi.c [new file with mode: 0644]
ubi-utils/src/libubigen.c
ubi-utils/src/list.c
ubi-utils/src/list.h
ubi-utils/src/peb.c [deleted file]
ubi-utils/src/peb.h [deleted file]
ubi-utils/src/pfi.c [deleted file]
ubi-utils/src/pfi2bin.c
ubi-utils/src/reader.c [deleted file]
ubi-utils/src/reader.h [deleted file]
ubi-utils/src/ubicrc32.c
ubi-utils/src/ubigen.h [deleted file]
ubi-utils/src/unubi.c
ubi-utils/src/unubi_analyze.c

index a6062a286b5955d59f450685137607ebda8a3d93..1f8e543a28d171b24b6f92db4b157cd311be99c0 100644 (file)
@@ -10,8 +10,7 @@ MANDIR=/usr/man
 INCLUDEDIR=/usr/include
 
 CC := $(CROSS)gcc
-CFLAGS := -I./inc -I./src -I$(KERNELHDR) $(OPTFLAGS) -Werror \
-       -Wwrite-strings -W -std=gnu99 -DPACKAGE_VERSION=\"1.0\"
+CFLAGS := -I./inc -I./src -I$(KERNELHDR) $(OPTFLAGS) -Werror -Wall -O0 -g
 
 PERLPROGS = mkpfi
 TARGETS = ubiupdate ubimkvol ubirmvol ubicrc32 ubinfo ubiattach ubidetach \
@@ -60,8 +59,8 @@ ubicrc32: ubicrc32.o crc32.o
 unubi: unubi.o crc32.o unubi_analyze.o eb_chain.o
        $(CC) $(LDFLAGS) -o $@ $^
 
-pfi2bin: pfi2bin.o common.o peb.o list.o crc32.o libubigen.o bootenv.o \
-               hashmap.o reader.o pfi.o
+pfi2bin: pfi2bin.o common.o list.o crc32.o libubigen.o bootenv.o \
+        hashmap.o libpfi.o common.o
        $(CC) $(LDFLAGS) -o $@ $^
 
 install: ${TARGETS}
similarity index 86%
rename from ubi-utils/src/pfi.h
rename to ubi-utils/inc/libpfi.h
index 8c5cc07b974e8b9671b21b825988250f5a738272..6aca4bec72cbdedb479d488a7076edf3d0c26fd5 100644 (file)
  */
 
 #include <stdio.h>             /* FILE */
+#include "list.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+struct pfi_ubi {
+       long long data_offs;
+       uint32_t data_size;
+       uint32_t alignment;
+       uint32_t *ids;
+       uint32_t ids_size;
+       char **names;
+       uint32_t names_size;
+       uint32_t size;
+       int vol_type;
+       int curr_seqnum; /* specifies the seqnum taken in an update,
+                           default: 0 (used by pfiflash, ubimirror) */
+       uint32_t crc;
+};
+
+int read_pfi_headers(struct list_entry **ubi_list, FILE *fp_pfi);
+int free_pfi_ubi(struct pfi_ubi **pfi_ubi);
+
 /* Definitions. */
 
 #define PFI_HDRVERSION 1       /* current header version */
@@ -73,13 +92,7 @@ extern "C" {
  */
 #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;
-
+struct pfi_header;
 
 /**
  * @brief Initialize a pfi header object.
@@ -89,7 +102,7 @@ typedef struct pfi_header *pfi_header;
  * @return      0 on success, otherwise:
  *              PFI_ENOMEM : no memory available for the handle.
  */
-int pfi_header_init (pfi_header *head);
+int pfi_header_init (struct pfi_header **head);
 
 
 /**
@@ -98,7 +111,7 @@ int pfi_header_init (pfi_header *head);
  * @param head  handle. head is invalid after calling this function.
  * @return      0 always.
  */
-int pfi_header_destroy (pfi_header *head);
+int pfi_header_destroy (struct pfi_header **head);
 
 
 /**
@@ -115,7 +128,7 @@ int pfi_header_destroy (pfi_header *head);
  *                              new value is not convertable e.g. not in
  *                              0xXXXXXXXX format.
  */
-int pfi_header_setvalue (pfi_header head,
+int pfi_header_setvalue (struct pfi_header *head,
                          const char *key, const char *value);
 
 
@@ -131,7 +144,7 @@ int pfi_header_setvalue (pfi_header head,
  *              PFI_EBADTYPE : value is not a string. This happens
  *                              when the key stores a string.
  */
-int pfi_header_setnumber (pfi_header head,
+int pfi_header_setnumber (struct pfi_header *head,
                           const char *key, uint32_t value);
 
 
@@ -146,12 +159,12 @@ int pfi_header_setnumber (pfi_header head,
  *              PFI_EUNDEF   : key was not found.
  *              PFI_EBADTYPE : stored value is not an integer but a string.
  */
-int pfi_header_getnumber (pfi_header head,
+int pfi_header_getnumber (struct pfi_header *head,
                           const char *key, uint32_t *value);
 
 
 static inline uint32_t
-pfi_getnumber(pfi_header head, const char *key)
+pfi_getnumber(struct pfi_header *head, const char *key)
 {
        uint32_t value;
        pfi_header_getnumber(head, key, &value);
@@ -169,7 +182,7 @@ pfi_getnumber(pfi_header head, const char *key)
  *              PFI_EUNDEF   : key was not found.
  *              PFI_EBADTYPE : stored value is not a string but an integer.
  */
-int pfi_header_getstring (pfi_header head,
+int pfi_header_getstring (struct pfi_header *head,
                           const char *key, char *value, size_t size);
 
 
@@ -183,7 +196,7 @@ int pfi_header_getstring (pfi_header head,
  *              PFI_ENOHEADER : wrong header version or magic number.
  *              -E*            : see <asm/errno.h>.
  */
-int pfi_header_write (FILE *out, pfi_header head);
+int pfi_header_write (FILE *out, struct pfi_header *head);
 
 
 /**
@@ -203,7 +216,7 @@ int pfi_header_write (FILE *out, pfi_header head);
  * required in those cases. For optional fields the checking must still be
  * done.
  */
-int pfi_header_read (FILE *in, pfi_header head);
+int pfi_header_read (FILE *in, struct pfi_header *head);
 
 
 /**
@@ -216,7 +229,7 @@ int pfi_header_read (FILE *in, pfi_header head);
  * @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);
+int pfi_header_dump (FILE *out, struct pfi_header *head);
 
 
 /*
@@ -232,7 +245,7 @@ int pfi_header_dump (FILE *out, pfi_header head);
  *              PFI_EINVAL       : func is not valid
  *              0 ok.
  */
-typedef int (* pfi_read_func)(FILE *in, pfi_header hdr, void *priv_data);
+typedef int (* pfi_read_func)(FILE *in, struct pfi_header *hdr, void *priv_data);
 
 int pfi_read (FILE *in, pfi_read_func func, void *priv_data);
 
diff --git a/ubi-utils/inc/libubigen.h b/ubi-utils/inc/libubigen.h
new file mode 100644 (file)
index 0000000..5315a72
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Authors: Frank Haverkamp
+ *          Artem Bityutskiy
+ */
+
+#ifndef __LIBUBIGEN_H__
+#define __LIBUBIGEN_H__
+
+#include <stdio.h>
+#include <asm/byteorder.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * struct ubigen_info - libubigen information.
+ * @leb_size: logical eraseblock size
+ * @peb_size: size of the physical eraseblock
+ * @min_io_size: minimum input/output unit size
+ * @vid_hdr_offs: offset of the VID header
+ * @data_offs: data offset
+ * @ubi_ver: UBI version
+ * @ec: initial erase counter
+ */
+struct ubigen_info
+{
+       int leb_size;
+       int peb_size;
+       int min_io_size;
+       int vid_hdr_offs;
+       int data_offs;
+       int ubi_ver;
+       long long ec;
+};
+
+/**
+ * struct ubigen_vol_info - information about a volume.
+ * @id: volume id
+ * @type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
+ * @alignment: volume alignment
+ * @data_pad: how many bytes are unused at the end of the each physical
+ *            eraseblock to satisfy the requested alignment
+ * @usable_leb_size: LEB size accessible for volume users
+ * @name: volume name
+ * @name_len: volume name length
+ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
+ *          %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+ * @used_ebs: total number of used logical eraseblocks in this volume (relevant
+ *            for static volumes only)
+ * @bytes: size of the volume contents in bytes (relevant for static volumes
+ *         only)
+ */
+struct ubigen_vol_info
+{
+       int id;
+       int type;
+       int alignment;
+       int data_pad;
+       int usable_leb_size;
+       const char *name;
+       int name_len;
+       int compat;
+       int used_ebs;
+       long long bytes;
+};
+
+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);
+struct ubi_vtbl_record *ubigen_create_empty_vtbl(int *size);
+void ubigen_add_volume(const struct ubigen_info *ui,
+                      const struct ubigen_vol_info *vi,
+                      struct ubi_vtbl_record *vtbl);
+int ubigen_write_volume(const struct ubigen_info *ui,
+                       const struct ubigen_vol_info *vi,
+                       long long bytes, FILE *in, FILE *out);
+int ubigen_write_layout_vol(const struct ubigen_info *ui,
+                           struct ubi_vtbl_record *vtbl, FILE *out);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__LIBUBIGEN_H__ */
index a6dd4dea564143fd7a8c96723b0fa7c359791856..5a4205f127277f71b25710be9c29dd9fcb70ef66 100644 (file)
@@ -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) {
index b27f866ffcef087cfcefb54fc81d600e190ed819..89094ab8986f843c3616c305de580e8c4feaab8d 100644 (file)
@@ -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 {                                             \
index 666e2171f83dd8ac3e1da989c2b3bf8246395e9e..6b1e50c42d9b646c4eba4d591bfb4b0941ac3c17 100644 (file)
@@ -1,83 +1,95 @@
 /*
- * Copyright (c) International Business Machines Corp., 2006
+ *  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
+ *  code or tables extracted from it, as desired without restriction.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ *  First, the polynomial itself and its table of feedback terms.  The
+ *  polynomial is
+ *  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
+ *  Note that we take it "backwards" and put the highest-order term in
+ *  the lowest-order bit.  The X^32 term is "implied"; the LSB is the
+ *  X^31 term, etc.  The X^0 term (usually shown as "+1") results in
+ *  the MSB being 1
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  Note that the usual hardware shift register implementation, which
+ *  is what we're using (we're merely optimizing it by doing eight-bit
+ *  chunks at a time) shifts bits into the lowest-order term.  In our
+ *  implementation, that means shifting towards the right.  Why do we
+ *  do it this way?  Because the calculated CRC must be transmitted in
+ *  order from highest-order term to lowest-order term.  UARTs transmit
+ *  characters in order from LSB to MSB.  By storing the CRC this way
+ *  we hand it to the UART in the order low-byte to high-byte; the UART
+ *  sends each low-bit to hight-bit; and the result is transmission bit
+ *  by bit from highest- to lowest-order term without requiring any bit
+ *  shuffling on our part.  Reception works similarly
  *
- * Author: Thomas Gleixner
- */
-
-/*
- * CRC32 functions
+ *  The feedback terms table consists of 256, 32-bit entries.  Notes
  *
- * Can be compiled as seperate object, but is included into the ipl source
- * so gcc can inline the functions. We optimize for size so the omission of
- * the function frame is helpful.
+ *      The table can be generated at runtime if desired; code to do so
+ *      is shown later.  It might not be obvious, but the feedback
+ *      terms simply represent the results of eight shift/xor opera
+ *      tions for all combinations of data and CRC register values
  *
+ *      The values must be right-shifted by eight bits by the "updcrc
+ *      logic; the shift must be unsigned (bring in zeroes).  On some
+ *      hardware you could probably optimize the shift in assembler by
+ *      using byte-swap instructions
+ *      polynomial $edb88320
  */
 
 #include <stdint.h>
-#include <crc32.h>
-
-/* CRC polynomial */
-#define CRC_POLY       0xEDB88320
-
-/**
- * init_crc32_table - Initialize crc table
- *
- * @table:     pointer to the CRC table which must be initialized
- *
- * Create CRC32 table for given polynomial. The table is created with
- * the lowest order term in the highest order bit. So the x^32 term
- * has to implied in the crc calculation function.
- */
-void init_crc32_table(uint32_t *table)
-{
-       uint32_t crc;
-       int i, j;
-
-       for (i = 0; i < 256; i++) {
-               crc = i;
-               for (j = 8; j > 0; j--) {
-                       if (crc & 1)
-                               crc = (crc >> 1) ^ CRC_POLY;
-                       else
-                               crc >>= 1;
-               }
-               table[i] = crc;
-       }
-}
-
-/**
- * clc_crc32 - Calculate CRC32 over a buffer
- *
- * @table:     pointer to the CRC table
- * @crc:       initial crc value
- * @buf:       pointer to the buffer
- * @len:       number of bytes to calc
- *
- * Returns the updated crc value.
- *
- * The algorithm resembles a hardware shift register, but calculates 8
- * bit at once.
- */
-uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf,
-                  int len)
-{
-       const unsigned char *p = buf;
 
-       while(--len >= 0)
-               crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-       return crc;
-}
+const uint32_t crc32_table[256] = {
+       0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+       0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+       0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+       0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+       0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+       0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+       0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+       0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+       0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+       0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+       0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+       0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+       0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+       0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+       0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+       0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+       0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+       0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+       0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+       0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+       0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+       0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+       0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+       0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+       0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+       0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+       0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+       0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+       0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+       0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+       0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+       0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+       0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+       0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+       0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+       0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+       0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+       0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+       0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+       0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+       0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+       0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+       0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+       0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+       0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+       0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+       0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+       0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+       0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+       0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+       0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+       0x2d02ef8dL
+};
index 31362b0944c15c0104f1c0d5ad1cc8c5e0181394..ee3145bc1597a05344c694d9bc3ba6639086a36f 100644 (file)
@@ -1,36 +1,19 @@
-#ifndef __CRC32_H__
-#define __CRC32_H__
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+#ifndef CRC32_H
+#define CRC32_H
 
-/*
- * Author: Thomas Gleixner
- *
- * CRC32 functions
- *
- * Can be compiled as seperate object, but is included into the ipl source
- * so gcc can inline the functions. We optimize for size so the omission of
- * the function frame is helpful.
- *
- */
 #include <stdint.h>
 
-void init_crc32_table(uint32_t *table);
-uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len);
+extern const uint32_t crc32_table[256];
 
-#endif /* __CRC32_H__ */
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+       static inline uint32_t
+crc32(uint32_t val, const void *ss, int len)
+{
+       const unsigned char *s = ss;
+       while (--len >= 0)
+               val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
+       return val;
+}
+
+#endif
diff --git a/ubi-utils/src/libpfi.c b/ubi-utils/src/libpfi.c
new file mode 100644 (file)
index 0000000..6de24ea
--- /dev/null
@@ -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;
+
+}
index 6aef29191fdca58790446de2e4a846b61663bd1f..c3a0f9cedb256ab0e2f3430883da1af737a9fe02 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (C) 2008 Nokia Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Generating UBI images.
  *
- * Author: Oliver Lohmann
- *
- * Add UBI headers to binary data.
+ * Authors: Oliver Lohmann
+ *          Artem Bityutskiy
  */
 
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdio.h>
-#include <errno.h>
+#include <unistd.h>
 #include <string.h>
-#include <mtd/ubi-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;
 }
index 6eb716bc351142dd934f71c2c91e960cc5568887..a7011586f953166b4ab6c9474bc033a1bd96d495 100644 (file)
 
 #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);
        }
 }
index e8452a2c4756e49b6d25a70b4db4b4ab4c5f1a2a..58bfe7e664347eec8a8e8a35287d2db80f0e35f9 100644 (file)
@@ -1,5 +1,3 @@
-#ifndef __LIST_H__
-#define __LIST_H__
 /*
  * Copyright (c) International Business Machines Corp., 2006
  *
  * 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 (file)
index 160a463..0000000
+++ /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 (file)
index 246bce8..0000000
+++ /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 (file)
index fa835e2..0000000
+++ /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;
-}
index cacf33fed27a5c36180e6c8c77feb3b6eabd3f1f..4289fca6da054ff5f51ac711455341596ea71bf8 100644 (file)
@@ -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
  */
 
 #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 (file)
index 0ea8c6d..0000000
+++ /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 (file)
index 715e464..0000000
+++ /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__ */
index 0f10b3114de96b04d0f5df12b07cd210d50d7c0c..806443955ec6c168d621fc3e6297000dd3d2c4e7 100644 (file)
@@ -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 (file)
index bf4b384..0000000
+++ /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__ */
index 5c1d3249b234e8ae2ca856a99878ab3dfb5a75dd..1d4b35b361935efd0f6f27d82c1d71347e3d36ec 100644 (file)
@@ -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));
index 2ab3b87fb9470187350c6ce9ad047f3c01a9fb26..3f3a48042218ed6b4e2c87fce3b6ac21887f428a 100644 (file)
@@ -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)))