summaryrefslogtreecommitdiff
path: root/ubi-utils
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-01-22 16:02:52 +0200
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-01-22 16:22:52 +0200
commit22f5fe49d60ea43524a902408b3112a78f2c5aae (patch)
tree873fd6ca0023a2e71eaf78292ead57af6f07e7f6 /ubi-utils
parentf1d0f2363471837b89bf89410251f263680b683a (diff)
ubi-utils: massive changes
This commit basically removes most of the old ubi utilities as they are barely maintainamble. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'ubi-utils')
-rw-r--r--ubi-utils/Makefile7
-rw-r--r--ubi-utils/inc/libpfi.h (renamed from ubi-utils/src/pfi.h)49
-rw-r--r--ubi-utils/inc/libubigen.h104
-rw-r--r--ubi-utils/src/bootenv.c8
-rw-r--r--ubi-utils/src/common.h1
-rw-r--r--ubi-utils/src/crc32.c156
-rw-r--r--ubi-utils/src/crc32.h47
-rw-r--r--ubi-utils/src/libpfi.c628
-rw-r--r--ubi-utils/src/libubigen.c665
-rw-r--r--ubi-utils/src/list.c52
-rw-r--r--ubi-utils/src/list.h55
-rw-r--r--ubi-utils/src/peb.c116
-rw-r--r--ubi-utils/src/peb.h41
-rw-r--r--ubi-utils/src/pfi.c458
-rw-r--r--ubi-utils/src/pfi2bin.c465
-rw-r--r--ubi-utils/src/reader.c482
-rw-r--r--ubi-utils/src/reader.h87
-rw-r--r--ubi-utils/src/ubicrc32.c9
-rw-r--r--ubi-utils/src/ubigen.h150
-rw-r--r--ubi-utils/src/unubi.c14
-rw-r--r--ubi-utils/src/unubi_analyze.c8
21 files changed, 1261 insertions, 2341 deletions
diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile
index a6062a2..1f8e543 100644
--- a/ubi-utils/Makefile
+++ b/ubi-utils/Makefile
@@ -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}
diff --git a/ubi-utils/src/pfi.h b/ubi-utils/inc/libpfi.h
index 8c5cc07..6aca4be 100644
--- a/ubi-utils/src/pfi.h
+++ b/ubi-utils/inc/libpfi.h
@@ -35,11 +35,30 @@
*/
#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
index 0000000..5315a72
--- /dev/null
+++ b/ubi-utils/inc/libubigen.h
@@ -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__ */
diff --git a/ubi-utils/src/bootenv.c b/ubi-utils/src/bootenv.c
index a6dd4de..5a4205f 100644
--- a/ubi-utils/src/bootenv.c
+++ b/ubi-utils/src/bootenv.c
@@ -282,7 +282,6 @@ bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t* ret_crc)
int rc;
char *buf = NULL;
size_t i = 0;
- uint32_t crc32_table[256];
if ((fp == NULL) || (env == NULL))
return -EINVAL;
@@ -317,8 +316,7 @@ bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t* ret_crc)
/* calculate crc to return */
if (ret_crc != NULL) {
- init_crc32_table(crc32_table);
- *ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size);
+ *ret_crc = crc32(UBI_CRC32_INIT, buf, size);
}
/* transfer to hashmap */
@@ -442,7 +440,6 @@ bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc)
int rc = 0;
size_t size = 0;
char *buf = NULL;
- uint32_t crc32_table[256];
if ((fp == NULL) || (env == NULL))
return -EINVAL;
@@ -458,8 +455,7 @@ bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc)
/* calculate crc to return */
if (ret_crc != NULL) {
- init_crc32_table(crc32_table);
- *ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size);
+ *ret_crc = crc32(UBI_CRC32_INIT, buf, size);
}
if (fwrite(buf, size, 1, fp) != 1) {
diff --git a/ubi-utils/src/common.h b/ubi-utils/src/common.h
index b27f866..89094ab 100644
--- a/ubi-utils/src/common.h
+++ b/ubi-utils/src/common.h
@@ -24,6 +24,7 @@ extern "C" {
#endif
#define MIN(a ,b) ((a) < (b) ? (a) : (b))
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/* Error messages */
#define errmsg(fmt, ...) do { \
diff --git a/ubi-utils/src/crc32.c b/ubi-utils/src/crc32.c
index 666e217..6b1e50c 100644
--- a/ubi-utils/src/crc32.c
+++ b/ubi-utils/src/crc32.c
@@ -1,83 +1,95 @@
/*
- * Copyright (c) International Business Machines Corp., 2006
+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * First, the polynomial itself and its table of feedback terms. The
+ * polynomial is
+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
+ * Note that we take it "backwards" and put the highest-order term in
+ * the lowest-order bit. The X^32 term is "implied"; the LSB is the
+ * X^31 term, etc. The X^0 term (usually shown as "+1") results in
+ * the MSB being 1
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Note that the usual hardware shift register implementation, which
+ * is what we're using (we're merely optimizing it by doing eight-bit
+ * chunks at a time) shifts bits into the lowest-order term. In our
+ * implementation, that means shifting towards the right. Why do we
+ * do it this way? Because the calculated CRC must be transmitted in
+ * order from highest-order term to lowest-order term. UARTs transmit
+ * characters in order from LSB to MSB. By storing the CRC this way
+ * we hand it to the UART in the order low-byte to high-byte; the UART
+ * sends each low-bit to hight-bit; and the result is transmission bit
+ * by bit from highest- to lowest-order term without requiring any bit
+ * shuffling on our part. Reception works similarly
*
- * Author: Thomas Gleixner
- */
-
-/*
- * CRC32 functions
+ * The feedback terms table consists of 256, 32-bit entries. Notes
*
- * Can be compiled as seperate object, but is included into the ipl source
- * so gcc can inline the functions. We optimize for size so the omission of
- * the function frame is helpful.
+ * The table can be generated at runtime if desired; code to do so
+ * is shown later. It might not be obvious, but the feedback
+ * terms simply represent the results of eight shift/xor opera
+ * tions for all combinations of data and CRC register values
*
+ * The values must be right-shifted by eight bits by the "updcrc
+ * logic; the shift must be unsigned (bring in zeroes). On some
+ * hardware you could probably optimize the shift in assembler by
+ * using byte-swap instructions
+ * polynomial $edb88320
*/
#include <stdint.h>
-#include <crc32.h>
-
-/* CRC polynomial */
-#define CRC_POLY 0xEDB88320
-
-/**
- * init_crc32_table - Initialize crc table
- *
- * @table: pointer to the CRC table which must be initialized
- *
- * Create CRC32 table for given polynomial. The table is created with
- * the lowest order term in the highest order bit. So the x^32 term
- * has to implied in the crc calculation function.
- */
-void init_crc32_table(uint32_t *table)
-{
- uint32_t crc;
- int i, j;
-
- for (i = 0; i < 256; i++) {
- crc = i;
- for (j = 8; j > 0; j--) {
- if (crc & 1)
- crc = (crc >> 1) ^ CRC_POLY;
- else
- crc >>= 1;
- }
- table[i] = crc;
- }
-}
-
-/**
- * clc_crc32 - Calculate CRC32 over a buffer
- *
- * @table: pointer to the CRC table
- * @crc: initial crc value
- * @buf: pointer to the buffer
- * @len: number of bytes to calc
- *
- * Returns the updated crc value.
- *
- * The algorithm resembles a hardware shift register, but calculates 8
- * bit at once.
- */
-uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf,
- int len)
-{
- const unsigned char *p = buf;
- while(--len >= 0)
- crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
- return crc;
-}
+const uint32_t crc32_table[256] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
diff --git a/ubi-utils/src/crc32.h b/ubi-utils/src/crc32.h
index 31362b0..ee3145b 100644
--- a/ubi-utils/src/crc32.h
+++ b/ubi-utils/src/crc32.h
@@ -1,36 +1,19 @@
-#ifndef __CRC32_H__
-#define __CRC32_H__
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+#ifndef CRC32_H
+#define CRC32_H
-/*
- * Author: Thomas Gleixner
- *
- * CRC32 functions
- *
- * Can be compiled as seperate object, but is included into the ipl source
- * so gcc can inline the functions. We optimize for size so the omission of
- * the function frame is helpful.
- *
- */
#include <stdint.h>
-void init_crc32_table(uint32_t *table);
-uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len);
+extern const uint32_t crc32_table[256];
-#endif /* __CRC32_H__ */
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+ static inline uint32_t
+crc32(uint32_t val, const void *ss, int len)
+{
+ const unsigned char *s = ss;
+ while (--len >= 0)
+ val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
+ return val;
+}
+
+#endif
diff --git a/ubi-utils/src/libpfi.c b/ubi-utils/src/libpfi.c
new file mode 100644
index 0000000..6de24ea
--- /dev/null
+++ b/ubi-utils/src/libpfi.c
@@ -0,0 +1,628 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * A library to work with pfi files.
+ *
+ * Authors Oliver Lohmann
+ * Andreas Arnez
+ * Joern Engel
+ * Frank Haverkamp
+ * Artem Bityutskiy
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <mtd/ubi-header.h>
+#include <libpfi.h>
+#include "common.h"
+#include "bootenv.h"
+
+#define PROGRAM_NAME "libpfi"
+
+#define PFI_MAGIC "PFI!\n"
+#define PFI_MAGIC_LEN (sizeof(PFI_MAGIC) - 1)
+#define PFI_DATA "DATA\n"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#define PFI_MANDATORY 0x0001
+#define PFI_STRING 0x0002
+#define PFI_LISTVALUE 0x0004
+#define PFI_MANDATORY_UBI 0x0008
+
+enum key_id {
+ /* version 1 */
+ key_version, /* must be index position 0! */
+ key_mode,
+ key_size,
+ key_crc,
+ key_label,
+ key_flags,
+ key_ubi_ids,
+ key_ubi_size,
+ key_ubi_type,
+ key_ubi_names,
+ key_ubi_alignment,
+ num_keys,
+};
+
+struct pfi_header {
+ uint8_t defined[num_keys]; /* reserve all possible keys even if
+ version does not require this. */
+ int mode_no; /* current mode no. -> can only increase */
+ union {
+ char *str;
+ uint32_t num;
+ } value[num_keys];
+};
+
+struct key_descriptor {
+ enum key_id id;
+ const char *name;
+ uint32_t flags;
+};
+
+static const struct key_descriptor key_desc_v1[] = {
+ { key_version, "version", PFI_MANDATORY },
+ { key_mode, "mode", PFI_MANDATORY | PFI_STRING },
+ { key_size, "size", PFI_MANDATORY },
+ { key_crc, "crc", PFI_MANDATORY },
+ { key_label, "label", PFI_MANDATORY | PFI_STRING },
+ { key_flags, "flags", PFI_MANDATORY },
+ { key_ubi_ids, "ubi_ids", PFI_MANDATORY_UBI | PFI_STRING },
+ { key_ubi_size, "ubi_size", PFI_MANDATORY_UBI },
+ { key_ubi_type, "ubi_type", PFI_MANDATORY_UBI | PFI_STRING },
+ { key_ubi_names, "ubi_names", PFI_MANDATORY_UBI | PFI_STRING },
+ { key_ubi_alignment, "ubi_alignment", PFI_MANDATORY_UBI },
+};
+
+static const struct key_descriptor *key_descriptors[] = {
+ NULL,
+ key_desc_v1, /* version 1 */
+};
+
+static const int key_descriptors_max[] = {
+ 0, /* version 0 */
+ sizeof(key_desc_v1)/sizeof(struct key_descriptor), /* version 1 */
+};
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static const char* modes[] = {"ubi"};
+
+/* latest version contains all possible keys */
+static const struct key_descriptor *key_desc = key_desc_v1;
+
+#define PFI_IS_UBI(mode) \
+ (((mode) != NULL) && (strcmp("ubi", (mode)) == 0))
+
+static int get_mode_no(const char *mode)
+{
+ int i;
+
+ for (i = 0; i < (int)ARRAY_SIZE(modes); i++)
+ if (strcmp(mode, modes[i]) == 0)
+ return i;
+ return -1;
+}
+
+static int
+find_key_by_name (const char *name)
+{
+ int i;
+
+ for (i = 0; i < num_keys; i++) {
+ if (strcmp(name, key_desc[i].name) == 0)
+ return i;
+ }
+ return -1;
+}
+
+static int
+check_valid (struct pfi_header *head)
+{
+ int i;
+ int max_keys;
+ uint32_t version;
+ const char *mode;
+ const struct key_descriptor *desc;
+ uint32_t to_check = PFI_MANDATORY;
+
+ /*
+ * For the validity check the list of possible keys depends on
+ * the version of the PFI file used.
+ */
+ version = head->value[key_version].num;
+ if (version > PFI_HDRVERSION)
+ return PFI_ENOHEADER;
+
+ max_keys = key_descriptors_max[version];
+ desc = key_descriptors[version];
+
+ if (!desc)
+ return PFI_ENOVERSION;
+
+ mode = head->value[key_mode].str;
+ if (PFI_IS_UBI(mode)) {
+ to_check |= PFI_MANDATORY_UBI;
+ }
+ else { /* neither UBI nor RAW == ERR */
+ return PFI_EINSUFF;
+ }
+
+ for (i = 0; i < max_keys; i++) {
+ if ((desc[i].flags & to_check) && !head->defined[i]) {
+ fprintf(stderr, "libpfi: %s missing\n", desc[i].name);
+ return PFI_EINSUFF;
+ }
+ }
+
+ return 0;
+}
+
+int pfi_header_init (struct pfi_header **head)
+{
+ int i;
+ struct pfi_header *self = malloc(sizeof(*self));
+
+ *head = self;
+ if (self == NULL)
+ return PFI_ENOMEM;
+
+ /* initialize maximum number of possible keys */
+ for (i = 0; i < num_keys; i++) {
+ memset(self, 0, sizeof(*self));
+ self->defined[i] = 0;
+ }
+
+ return 0;
+}
+
+int pfi_header_destroy (struct pfi_header **head)
+{
+ int i;
+ struct pfi_header *self = *head;
+
+ for (i = 0; i < num_keys; i++) {
+ if (self->defined[i] && (key_desc[i].flags & PFI_STRING) &&
+ self->value[i].str) {
+ free(self->value[i].str);
+ }
+ }
+ free(*head);
+ *head = NULL;
+ return 0;
+}
+
+int pfi_header_setnumber (struct pfi_header *head,
+ const char *key, uint32_t value)
+{
+ int key_id = find_key_by_name(key);
+
+ if (key_id < 0)
+ return PFI_EUNDEF;
+
+ if (key_desc[key_id].flags & PFI_STRING)
+ return PFI_EBADTYPE;
+
+ head->value[key_id].num = value;
+ head->defined[key_id] = 1;
+ return 0;
+}
+
+int pfi_header_setvalue (struct pfi_header *head,
+ const char *key, const char *value)
+{
+ int key_id = find_key_by_name(key);
+
+ if (value == NULL)
+ return PFI_EINSUFF;
+
+ if ((key_id < 0) || (key_id >= num_keys))
+ return PFI_EUNDEF;
+
+ if (key_desc[key_id].flags & PFI_STRING) {
+ /*
+ * The value is a string. Copy to a newly allocated
+ * buffer. Delete the old value, if already set.
+ */
+ size_t len = strlen(value) + 1;
+ char *old_str = NULL;
+ char *str;
+
+ old_str = head->value[key_id].str;
+ if (old_str != NULL)
+ free(old_str);
+
+ str = head->value[key_id].str = (char *) malloc(len);
+ if (str == NULL)
+ return PFI_ENOMEM;
+
+ strcpy(str, value);
+ } else {
+ int len;
+ int ret;
+ /* FIXME: here we assume that the value is always
+ given in hex and starts with '0x'. */
+ ret = sscanf(value, "0x%x%n", &head->value[key_id].num, &len);
+ if (ret < 1 || value[len] != '\0')
+ return PFI_EBADTYPE;
+ }
+ head->defined[key_id] = 1;
+ return 0;
+}
+
+int pfi_header_getnumber (struct pfi_header *head,
+ const char *key, uint32_t *value)
+{
+ int key_id = find_key_by_name(key);
+
+ if (key_id < 0)
+ return PFI_EUNDEF;
+
+ if (key_desc[key_id].flags & PFI_STRING)
+ return PFI_EBADTYPE;
+
+ if (!head->defined[key_id])
+ return PFI_EUNDEF;
+
+ *value = head->value[key_id].num;
+ return 0;
+}
+
+int pfi_header_getstring (struct pfi_header *head,
+ const char *key, char *value, size_t size)
+{
+ int key_id = find_key_by_name(key);
+
+ if (key_id < 0)
+ return PFI_EUNDEF;
+
+ if (!(key_desc[key_id].flags & PFI_STRING))
+ return PFI_EBADTYPE;
+
+ if (!head->defined[key_id])
+ return PFI_EUNDEF;
+
+ strncpy(value, head->value[key_id].str, size-1);
+ value[size-1] = '\0';
+ return 0;
+}
+
+int pfi_header_read(FILE *in, struct pfi_header *head)
+{
+ char mode[PFI_KEYWORD_LEN];
+ char buf[256];
+
+ if (fread(buf, 1, PFI_MAGIC_LEN, in) != PFI_MAGIC_LEN) {
+ errmsg("cannot read %d bytes", PFI_MAGIC_LEN);
+ perror("fread");
+ return -1;
+ }
+
+ if (memcmp(buf, PFI_MAGIC, PFI_MAGIC_LEN) != 0) {
+ if (memcmp(buf, PFI_DATA, PFI_MAGIC_LEN) == 0)
+ return 1;
+
+ errmsg("PFI magic \"%s\" not found", PFI_MAGIC);
+ return -1;
+ }
+
+ while (fgets(buf, sizeof(buf), in) != NULL && buf[0] != '\n') {
+ char *value;
+ char *end;
+ value = strchr(buf, '=');
+ if (value == NULL)
+ return PFI_ENOHEADER;
+
+ *value = '\0';
+ value++;
+ end = strchr(value, '\n');
+ if (end)
+ *end = '\0';
+
+ if (pfi_header_setvalue(head, buf, value))
+ return PFI_ENOHEADER;
+ }
+
+ if (check_valid(head) != 0)
+ return PFI_ENOHEADER;
+
+ /* set current mode no. in head */
+ pfi_header_getstring(head, "mode", mode, PFI_KEYWORD_LEN);
+ if (head->mode_no > get_mode_no(mode)) {
+ return PFI_EMODE;
+ }
+ head->mode_no = get_mode_no(mode);
+ return 0;
+}
+int
+read_pfi_ubi(struct pfi_header *pfi_hd, struct pfi_ubi **pfi_ubi,
+ const char *label)
+{
+ int err = 0;
+ const char** tmp_names = NULL;
+ char tmp_str[PFI_KEYWORD_LEN];
+ bootenv_list_t ubi_id_list = NULL;
+ bootenv_list_t ubi_name_list = NULL;
+ struct pfi_ubi *res;
+ uint32_t i;
+ size_t size;
+
+ res = (struct pfi_ubi *) calloc(1, sizeof(struct pfi_ubi));
+ if (!res)
+ return -ENOMEM;
+
+ err = pfi_header_getnumber(pfi_hd, "size", &(res->data_size));
+ if (err != 0) {
+ errmsg("cannot read 'size' from PFI.");
+ goto err;
+ }
+
+ err = pfi_header_getnumber(pfi_hd, "crc", &(res->crc));
+ if (err != 0) {
+ errmsg("cannot read 'crc' from PFI.");
+ goto err;
+ }
+
+ err = pfi_header_getstring(pfi_hd, "ubi_ids", tmp_str, PFI_KEYWORD_LEN);
+ if (err != 0) {
+ errmsg("cannot read 'ubi_ids' from PFI.");
+ goto err;
+ }
+
+ err = bootenv_list_create(&ubi_id_list);
+ if (err != 0) {
+ goto err;
+ }
+ err = bootenv_list_create(&ubi_name_list);
+ if (err != 0) {
+ goto err;
+ }
+
+ err = bootenv_list_import(ubi_id_list, tmp_str);
+ if (err != 0) {
+ errmsg("cannot translate PFI value: %s", tmp_str);
+ goto err;
+ }
+
+ err = bootenv_list_to_num_vector(ubi_id_list, &size,
+ &(res->ids));
+ res->ids_size = size;
+ if (err != 0) {
+ errmsg("cannot create numeric value array: %s", tmp_str);
+ goto err;
+ }
+
+ if (res->ids_size == 0) {
+ err = -1;
+ errmsg("sanity check failed: No ubi_ids specified.");
+ goto err;
+ }
+
+ err = pfi_header_getstring(pfi_hd, "ubi_type",
+ tmp_str, PFI_KEYWORD_LEN);
+ if (err != 0) {
+ errmsg("cannot read 'ubi_type' from PFI.");
+ goto err;
+ }
+ if (strcmp(tmp_str, "static") == 0)
+ res->vol_type = UBI_VID_STATIC;
+ else if (strcmp(tmp_str, "dynamic") == 0)
+ res->vol_type = UBI_VID_DYNAMIC;
+ else {
+ errmsg("unknown ubi_type in PFI.");
+ goto err;
+ }
+
+ err = pfi_header_getnumber(pfi_hd, "ubi_alignment", &(res->alignment));
+ if (err != 0) {
+ errmsg("cannot read 'ubi_alignment' from PFI.");
+ goto err;
+ }
+
+ err = pfi_header_getnumber(pfi_hd, "ubi_size", &(res->size));
+ if (err != 0) {
+ errmsg("cannot read 'ubi_size' from PFI.");
+ goto err;
+ }
+
+ err = pfi_header_getstring(pfi_hd, "ubi_names",
+ tmp_str, PFI_KEYWORD_LEN);
+ if (err != 0) {
+ errmsg("cannot read 'ubi_names' from PFI.");
+ goto err;
+ }
+
+ err = bootenv_list_import(ubi_name_list, tmp_str);
+ if (err != 0) {
+ errmsg("cannot translate PFI value: %s", tmp_str);
+ goto err;
+ }
+ err = bootenv_list_to_vector(ubi_name_list, &size,
+ &(tmp_names));
+ res->names_size = size;
+ if (err != 0) {
+ errmsg("cannot create string array: %s", tmp_str);
+ goto err;
+ }
+
+ if (res->names_size != res->ids_size) {
+ errmsg("sanity check failed: ubi_ids list does not match "
+ "sizeof ubi_names list.");
+ err = -1;
+ }
+
+ /* copy tmp_names to own structure */
+ res->names = calloc(1, res->names_size * sizeof (char*));
+ if (res->names == NULL)
+ goto err;
+
+ for (i = 0; i < res->names_size; i++) {
+ res->names[i] = calloc(PFI_UBI_VOL_NAME_LEN + 1, sizeof(char));
+ if (res->names[i] == NULL)
+ goto err;
+ strncpy(res->names[i], tmp_names[i], PFI_UBI_VOL_NAME_LEN + 1);
+ }
+
+ goto out;
+
+ err:
+ if (res) {
+ if (res->names) {
+ for (i = 0; i < res->names_size; i++) {
+ if (res->names[i]) {
+ free(res->names[i]);
+ }
+ }
+ free(res->names);
+ }
+ if (res->ids) {
+ free(res->ids);
+ }
+ free(res);
+ res = NULL;
+ }
+
+ out:
+ bootenv_list_destroy(&ubi_id_list);
+ bootenv_list_destroy(&ubi_name_list);
+ if (tmp_names != NULL)
+ free(tmp_names);
+ *pfi_ubi = res;
+ return err;
+}
+
+int
+free_pfi_ubi(struct pfi_ubi **pfi_ubi)
+{
+ size_t i;
+ struct pfi_ubi *tmp = *pfi_ubi;
+ if (tmp) {
+ if (tmp->ids)
+ free(tmp->ids);
+ if (tmp->names) {
+ for (i = 0; i < tmp->names_size; i++) {
+ if (tmp->names[i]) {
+ free(tmp->names[i]);
+ }
+ }
+ free(tmp->names);
+ }
+ free(tmp);
+ }
+ *pfi_ubi = NULL;
+
+ return 0;
+}
+
+int read_pfi_headers(struct list_entry **ubi_list, FILE *fp_pfi)
+{
+ int err = 0;
+ long long data_offs = 0;
+ long fpos;
+ char mode[PFI_KEYWORD_LEN];
+ char label[PFI_LABEL_LEN];
+ struct list_entry *tmp;
+
+ *ubi_list = list_empty(); struct pfi_ubi *ubi = NULL;
+ struct pfi_header *pfi_header = NULL;
+
+ /* read all headers from PFI and store them in lists */
+ err = pfi_header_init(&pfi_header);
+ if (err != 0) {
+ errmsg("cannot initialize pfi header.");
+ goto err;
+ }
+ while ((err == 0) && !feof(fp_pfi)) {
+ err = pfi_header_read(fp_pfi, pfi_header);
+ if (err != 0) {
+ if (err == 1) {
+ err = 0;
+ break; /* data section starts,
+ all headers read */
+ }
+ else {
+ goto err;
+ }
+ }
+ err = pfi_header_getstring(pfi_header, "label", label,
+ PFI_LABEL_LEN);
+ if (err != 0) {
+ errmsg("cannot read 'label' from PFI.");
+ goto err;
+ }
+ err = pfi_header_getstring(pfi_header, "mode", mode,
+ PFI_KEYWORD_LEN);
+ if (err != 0) {
+ errmsg("cannot read 'mode' from PFI.");
+ goto err;
+ }
+ if (strcmp(mode, "ubi") == 0) {
+ err = read_pfi_ubi(pfi_header, &ubi, label);
+ if (err != 0) {
+ goto err;
+ }
+ *ubi_list = append_elem(ubi, *ubi_list);
+ }
+ else {
+ errmsg("recvieved unknown mode from PFI: %s", mode);
+ goto err;
+ }
+ ubi->data_offs = data_offs;
+ data_offs += ubi->data_size;
+ }
+
+ fpos = ftell(fp_pfi);
+ if (fpos == -1) {
+ errmsg("ftell returned error");
+ perror("ftell");
+ goto err;
+ }
+
+ list_for_each(ubi, tmp, *ubi_list)
+ ubi->data_offs += fpos;
+
+ goto out;
+
+ err:
+ *ubi_list = remove_all((free_func_t)&free_pfi_ubi, *ubi_list);
+ out:
+ pfi_header_destroy(&pfi_header);
+ return err;
+
+}
diff --git a/ubi-utils/src/libubigen.c b/ubi-utils/src/libubigen.c
index 6aef291..c3a0f9c 100644
--- a/ubi-utils/src/libubigen.c
+++ b/ubi-utils/src/libubigen.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) International Business Machines Corp., 2006
+ * Copyright (C) 2008 Nokia Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,473 +15,297 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Generating UBI images.
*
- * Author: Oliver Lohmann
- *
- * Add UBI headers to binary data.
+ * Authors: Oliver Lohmann
+ * Artem Bityutskiy
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
-#include <errno.h>
+#include <unistd.h>
#include <string.h>
-#include <mtd/ubi-header.h>
-#include "config.h"
-#include "ubigen.h"
+#include <mtd/ubi-header.h>
+#include <libubigen.h>
#include "crc32.h"
+#include "common.h"
-#define UBI_NAME_SIZE 256
-#define DEFAULT_VID_OFFSET ((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE))
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-static uint32_t crc32_table[256];
-
-struct ubi_info {
- struct ubi_vid_hdr* v; /* Volume ID header */
- struct ubi_ec_hdr* ec; /* Erase count header */
-
- FILE* fp_in; /* Input Stream */
- FILE* fp_out; /* Output stream */
-
- size_t peb_size; /* Physical EB size in bytes */
- size_t leb_size; /* Size of a logical EB in a physical EB */
- size_t leb_total; /* Total input size in logical EB */
- size_t alignment; /* Block alignment */
- size_t data_pad; /* Size of padding in each physical EB */
-
- size_t bytes_total; /* Total input size in bytes */
- size_t bytes_read; /* Nymber of read bytes (total) */
-
- uint32_t blks_written; /* Number of written logical EB */
-
- uint8_t* buf; /* Allocated buffer */
- uint8_t* ptr_ec_hdr; /* Pointer to EC hdr in buf */
- uint8_t* ptr_vid_hdr; /* Pointer to VID hdr in buf */
- uint8_t* ptr_data; /* Pointer to data region in buf */
-};
-
-
-static uint32_t
-byte_to_blk(uint64_t byte, uint32_t peb_size)
-{
- return (byte % peb_size) == 0
- ? (byte / peb_size)
- : (byte / peb_size) + 1;
-}
+#define PROGRAM_NAME "libubigen"
-static int
-validate_ubi_info(ubi_info_t u)
-{
- if ((u->v->vol_type != UBI_VID_DYNAMIC) &&
- (u->v->vol_type != UBI_VID_STATIC)) {
- return EUBIGEN_INVALID_TYPE;
- }
-
- if (__be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) {
- return EUBIGEN_INVALID_HDR_OFFSET;
- }
-
- return 0;
-}
-
-static int
-skip_blks(ubi_info_t u, uint32_t blks)
-{
- uint32_t i;
- size_t read = 0, to_read = 0;
-
- /* Step to a maximum of leb_total - 1 to keep the
- restrictions. */
- for (i = 0; i < MIN(blks, u->leb_total-1); i++) {
- /* Read in data */
- to_read = MIN(u->leb_size,
- (u->bytes_total - u->bytes_read));
- read = fread(u->ptr_data, 1, to_read, u->fp_in);
- if (read != to_read) {
- return -EIO;
- }
- u->bytes_read += read;
- u->blks_written++;
- }
-
- return 0;
-}
-
-static void
-clear_buf(ubi_info_t u)
-{
- memset(u->buf, 0xff, u->peb_size);
-}
-
-static void
-write_ec_hdr(ubi_info_t u)
+/**
+ * ubigen_create_empty_vtbl - creates empty volume table.
+ * @size: physical eraseblock size on input, size of the volume table on output
+ *
+ * This function creates an empty volume table and returns a pointer to it in
+ * case of success and %NULL in case of failure. The volume table size is
+ * returned in @size which has to contain PEB size on input.
+ */
+struct ubi_vtbl_record *ubigen_create_empty_vtbl(int *size)
{
- memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE);
-}
+ struct ubi_vtbl_record *vtbl;
+ int i;
-static int
-fill_data_buffer_from_file(ubi_info_t u, size_t* read)
-{
- size_t to_read = 0;
+ if (*size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE)
+ *size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
- if (u-> fp_in == NULL)
- return -EIO;
+ vtbl = calloc(1, *size);
+ if (!vtbl)
+ return NULL;
- to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read));
- *read = fread(u->ptr_data, 1, to_read, u->fp_in);
- if (*read != to_read) {
- return -EIO;
+ for (i = 0; i < UBI_MAX_VOLUMES; i++) {
+ uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i],
+ UBI_VTBL_RECORD_SIZE_CRC);
+ vtbl[i].crc = __cpu_to_be32(crc);
}
- return 0;
-}
-static void
-add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action)
-{
- uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
- u->ptr_data, data_size);
-
- u->v->data_size = __cpu_to_be32(data_size);
- u->v->data_crc = __cpu_to_be32(crc);
-
- if (action & BROKEN_DATA_CRC) {
- u->v->data_crc =
- __cpu_to_be32(__be32_to_cpu(u->v->data_crc) + 1);
- }
- if (action & BROKEN_DATA_SIZE) {
- u->v->data_size =
- __cpu_to_be32(__be32_to_cpu(u->v->data_size) + 1);
- }
+ return vtbl;
}
-static void
-write_vid_hdr(ubi_info_t u, ubigen_action_t action)
+/**
+ * ubigen_info_init - initialize libubigen.
+ * @ui: libubigen information
+ * @peb_size: flash physical eraseblock size
+ * @min_io_size: flash minimum input/output unit size
+ * @subpage_size: flash sub-page, if present (has to be equivalent to
+ * @min_io_size if does not exist)
+ * @vid_hdr_offs: offset of the VID header
+ * @ubi_ver: UBI version
+ * @ec: initial erase counter
+ */
+void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
+ int subpage_size, int vid_hdr_offs, int ubi_ver,
+ long long ec)
{
- uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
- u->v, UBI_VID_HDR_SIZE_CRC);
- /* Write VID header */
- u->v->hdr_crc = __cpu_to_be32(crc);
- if (action & BROKEN_HDR_CRC) {
- u->v->hdr_crc = __cpu_to_be32(__be32_to_cpu(u->v->hdr_crc) + 1);
- }
- memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE);
+ if (!vid_hdr_offs)
+ vid_hdr_offs = subpage_size;
+
+ ui->peb_size = peb_size;
+ ui->min_io_size = min_io_size;
+ ui->vid_hdr_offs = vid_hdr_offs;
+ ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1;
+ ui->data_offs /= min_io_size;
+ ui->data_offs *= min_io_size;
+ ui->leb_size = peb_size - ui->data_offs;
+ ui->ubi_ver = ubi_ver;
+ ui->ec = ec;
}
-static int
-write_to_output_stream(ubi_info_t u)
+/**
+ * ubigen_add_volume - add a volume to the volume table.
+ * @vol_id: volume ID
+ * @bytes: volume size in bytes
+ * @alignment: volume alignment
+ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ * @name: volume name
+ * @ui: libubigen information
+ * @vtbl: volume table to add to
+ *
+ * This function adds volume described by input parameters to the volume table
+ * @vtbl.
+ */
+void ubigen_add_volume(const struct ubigen_info *ui,
+ const struct ubigen_vol_info *vi,
+ struct ubi_vtbl_record *vtbl)
{
- size_t written;
-
- written = fwrite(u->buf, 1, u->peb_size, u->fp_out);
- if (written != u->peb_size) {
- return -EIO;
- }
- return 0;
+ struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
+ uint32_t tmp;
+
+ memset(vtbl_rec, '\0', sizeof(struct ubi_vtbl_record));
+ tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size;
+ vtbl_rec->reserved_pebs = __cpu_to_be32(tmp);
+ vtbl_rec->alignment = __cpu_to_be32(vi->alignment);
+ vtbl_rec->vol_type = vi->type;
+ tmp = ui->leb_size % vi->alignment;
+ vtbl_rec->data_pad = __cpu_to_be32(tmp);
+
+ memcpy(vtbl_rec->name, vi->name, vi->name_len);
+ vtbl_rec->name[vi->name_len] = '\0';
+ vtbl_rec->name_len = __cpu_to_be16(vi->name_len);
+
+ tmp = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
+ vtbl_rec->crc = __cpu_to_be32(tmp);
}
-int
-ubigen_write_leb(ubi_info_t u, ubigen_action_t action)
+/**
+ * init_ec_hdr - initialize EC header.
+ * @ui: libubigen information
+ * @hdr: the EC header to initialize
+ */
+static void init_ec_hdr(const struct ubigen_info *ui,
+ struct ubi_ec_hdr *hdr)
{
- int rc = 0;
- size_t read = 0;
-
- clear_buf(u);
- write_ec_hdr(u);
-
- rc = fill_data_buffer_from_file(u, &read);
- if (rc != 0)
- return rc;
-
- if (u->v->vol_type == UBI_VID_STATIC) {
- add_static_info(u, read, action);
- }
+ uint32_t crc;
- u->v->lnum = __cpu_to_be32(u->blks_written);
+ memset(hdr, '\0', sizeof(struct ubi_ec_hdr));
- if (action & MARK_AS_UPDATE) {
- u->v->copy_flag = (u->v->copy_flag)++;
- }
+ hdr->magic = __cpu_to_be32(UBI_EC_HDR_MAGIC);
+ hdr->version = ui->ubi_ver;
+ hdr->ec = __cpu_to_be64(ui->ec);
+ hdr->vid_hdr_offset = __cpu_to_be32(ui->vid_hdr_offs);
- write_vid_hdr(u, action);
- rc = write_to_output_stream(u);
- if (rc != 0)
- return rc;
+ hdr->data_offset = __cpu_to_be32(ui->data_offs);
- /* Update current handle */
- u->bytes_read += read;
- u->blks_written++;
- return 0;
+ crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+ hdr->hdr_crc = __cpu_to_be32(crc);
}
-int
-ubigen_write_complete(ubi_info_t u)
+/**
+ * init_vid_hdr - initialize VID header.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @hdr: the VID header to initialize
+ * @lnum: logical eraseblock number
+ * @data: the contents of the LEB (static volumes only)
+ * @data_size: amount of data in this LEB (static volumes only)
+ *
+ * Note, @used_ebs, @data and @data_size are ignored in case of dynamic
+ * volumes.
+ */
+static void init_vid_hdr(const struct ubigen_info *ui,
+ const struct ubigen_vol_info *vi,
+ struct ubi_vid_hdr *hdr, int lnum,
+ const void *data, int data_size)
{
- size_t i;
- int rc = 0;
+ uint32_t crc;
- for (i = 0; i < u->leb_total; i++) {
- rc = ubigen_write_leb(u, NO_ERROR);
- if (rc != 0)
- return rc;
+ memset(hdr, '\0', sizeof(struct ubi_vid_hdr));
+
+ hdr->magic = __cpu_to_be32(UBI_VID_HDR_MAGIC);
+ hdr->version = ui->ubi_ver;
+ hdr->vol_type = vi->type;
+ hdr->vol_id = __cpu_to_be32(vi->id);
+ hdr->lnum = __cpu_to_be32(lnum);
+ hdr->data_pad = __cpu_to_be32(vi->data_pad);
+ hdr->compat = vi->compat;
+
+ if (vi->type == UBI_VID_STATIC) {
+ hdr->data_size = __cpu_to_be32(data_size);
+ hdr->used_ebs = __cpu_to_be32(vi->used_ebs);
+ crc = crc32(UBI_CRC32_INIT, data, data_size);
+ hdr->data_crc = __cpu_to_be32(crc);
}
- return 0;
+ crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
+ hdr->hdr_crc = __cpu_to_be32(crc);
}
-int
-ubigen_write_broken_update(ubi_info_t u, uint32_t blk)
+/**
+ * ubigen_write_volume - write UBI volume.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @bytes: volume size in bytes
+ * @in: input file descriptor (has to be properly seeked)
+ * @out: output file descriptor
+ *
+ * This function reads the contents of the volume from the input file @in and
+ * writes the UBI volume to the output file @out. Returns zero on success and
+ * %-1 on failure.
+ */
+int ubigen_write_volume(const struct ubigen_info *ui,
+ const struct ubigen_vol_info *vi,
+ long long bytes, FILE *in, FILE *out)
{
- int rc = 0;
-
- rc = skip_blks(u, blk);
- if (rc != 0)
- return rc;
-
- rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC);
- if (rc != 0)
- return rc;
-
-
- return 0;
-}
+ int len = vi->usable_leb_size, rd, lnum = 0;
+ char inbuf[ui->leb_size], outbuf[ui->peb_size];
+
+ memset(outbuf, 0xFF, ui->data_offs);
+ init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf);
+
+ while (bytes) {
+ int l;
+ struct ubi_vid_hdr *vid_hdr;
+
+ if (bytes < len)
+ len = bytes;
+ bytes -= len;
+
+ l = len;
+ do {
+ rd = fread(inbuf + len - l, 1, l, in);
+ if (rd == 0) {
+ if (ferror(in))
+ errmsg("cannot read %d bytes from the input"
+ " file", l);
+ else
+ errmsg("not enough data in the input file");
+ return -1;
+ }
+
+ l -= rd;
+ } while (l);
+
+ vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+ init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
+
+ memcpy(outbuf + ui->data_offs, inbuf, len);
+ memset(outbuf + ui->data_offs + len, 0xFF,
+ ui->peb_size - ui->data_offs - len);
+
+ if (fwrite(outbuf, 1, ui->peb_size, out) != ui->peb_size) {
+ errmsg("cannot write %d bytes from the output"
+ " file", l);
+ return -1;
+ }
-void
-dump_info(ubi_info_t u ubi_unused)
-{
-#ifdef DEBUG
- int err = 0;
- if (!u) {
- fprintf(stderr, "<empty>");
- return;
- }
- if (!u->ec) {
- fprintf(stderr, "<ec-empty>");
- err = 1;
- }
- if (!u->v) {
- fprintf(stderr, "<v-empty>");
- err = 1;
+ lnum += 1;
}
- if (err) return;
-
- fprintf(stderr, "ubi volume\n");
- fprintf(stderr, "version : %8d\n", u->v->version);
- fprintf(stderr, "vol_id : %8d\n", __be32_to_cpu(u->v->vol_id));
- fprintf(stderr, "vol_type : %8s\n",
- u->v->vol_type == UBI_VID_STATIC ?
- "static" : "dynamic");
- fprintf(stderr, "used_ebs : %8d\n",
- __be32_to_cpu(u->v->used_ebs));
- fprintf(stderr, "peb_size : 0x%08x\n", u->peb_size);
- fprintf(stderr, "leb_size : 0x%08x\n", u->leb_size);
- fprintf(stderr, "data_pad : 0x%08x\n",
- __be32_to_cpu(u->v->data_pad));
- fprintf(stderr, "leb_total : %8d\n", u->leb_total);
- fprintf(stderr, "header offs : 0x%08x\n",
- __be32_to_cpu(u->ec->vid_hdr_offset));
- fprintf(stderr, "bytes_total : %8d\n", u->bytes_total);
- fprintf(stderr, " + in MiB : %8.2f M\n",
- ((float)(u->bytes_total)) / 1024 / 1024);
- fprintf(stderr, "-------------------------------\n\n");
-#else
- return;
-#endif
-}
-int
-ubigen_destroy(ubi_info_t *u)
-{
- if (u == NULL)
- return -EINVAL;
-
- ubi_info_t tmp = *u;
-
- if (tmp) {
- if (tmp->v)
- free(tmp->v);
- if (tmp->ec)
- free(tmp->ec);
- if (tmp->buf)
- free(tmp->buf);
- free(tmp);
- }
- *u = NULL;
return 0;
}
-void
-ubigen_init(void)
-{
- init_crc32_table(crc32_table);
-}
-
-int
-ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type,
- uint32_t peb_size, uint64_t ec, uint32_t alignment,
- uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag,
- size_t data_size, FILE* fp_in, FILE* fp_out)
+/**
+ * ubigen_write_layout_vol - write UBI layout volume
+ * @ui: libubigen information
+ * @vtbl: volume table
+ * @out: output file stream
+ *
+ * This function creates the UBI layout volume which contains 2 copies of the
+ * volume table. Returns zero in case of success and %-1 in case of failure.
+ */
+int ubigen_write_layout_vol(const struct ubigen_info *ui,
+ struct ubi_vtbl_record *vtbl, FILE *out)
{
- int rc = 0;
- ubi_info_t res = NULL;
- uint32_t crc;
- uint32_t data_offset;
-
- if (alignment == 0) {
- rc = EUBIGEN_INVALID_ALIGNMENT;
- goto ubigen_create_err;
- }
- if ((fp_in == NULL) || (fp_out == NULL)) {
- rc = -EINVAL;
- goto ubigen_create_err;
- }
-
- res = (ubi_info_t) calloc(1, sizeof(struct ubi_info));
- if (res == NULL) {
- rc = -ENOMEM;
- goto ubigen_create_err;
- }
-
- res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr));
- if (res->v == NULL) {
- rc = -ENOMEM;
- goto ubigen_create_err;
- }
-
- res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr));
- if (res->ec == NULL) {
- rc = -ENOMEM;
- goto ubigen_create_err;
- }
-
- /* data which is needed in the general process */
- vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET;
- data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE;
- res->bytes_total = data_size;
- res->peb_size = peb_size ? peb_size : DEFAULT_BLOCKSIZE;
- res->data_pad = (res->peb_size - data_offset) % alignment;
- res->leb_size = res->peb_size - data_offset - res->data_pad;
- res->leb_total = byte_to_blk(data_size, res->leb_size);
- res->alignment = alignment;
-
- if ((res->peb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) {
- rc = EUBIGEN_TOO_SMALL_EB;
- goto ubigen_create_err;
- }
- res->fp_in = fp_in;
- res->fp_out = fp_out;
-
- /* vid hdr data which doesn't change */
- res->v->magic = __cpu_to_be32(UBI_VID_HDR_MAGIC);
- res->v->version = version ? version : UBI_VERSION;
- res->v->vol_type = vol_type;
- res->v->vol_id = __cpu_to_be32(vol_id);
- res->v->compat = compat_flag;
- res->v->data_pad = __cpu_to_be32(res->data_pad);
-
- /* static only: used_ebs */
- if (res->v->vol_type == UBI_VID_STATIC) {
- res->v->used_ebs = __cpu_to_be32(byte_to_blk
- (res->bytes_total,
- res->leb_size));
- }
-
- /* ec hdr (fixed, doesn't change) */
- res->ec->magic = __cpu_to_be32(UBI_EC_HDR_MAGIC);
- res->ec->version = version ? version : UBI_VERSION;
- res->ec->ec = __cpu_to_be64(ec);
- res->ec->vid_hdr_offset = __cpu_to_be32(vid_hdr_offset);
-
- res->ec->data_offset = __cpu_to_be32(data_offset);
-
- crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec,
- UBI_EC_HDR_SIZE_CRC);
- res->ec->hdr_crc = __cpu_to_be32(crc);
-
- /* prepare a read buffer */
- res->buf = (uint8_t*) malloc (res->peb_size * sizeof(uint8_t));
- if (res->buf == NULL) {
- rc = -ENOMEM;
- goto ubigen_create_err;
- }
-
- /* point to distinct regions within the buffer */
- res->ptr_ec_hdr = res->buf;
- res->ptr_vid_hdr = res->buf + __be32_to_cpu(res->ec->vid_hdr_offset);
- res->ptr_data = res->buf + __be32_to_cpu(res->ec->vid_hdr_offset)
- + UBI_VID_HDR_SIZE;
-
- rc = validate_ubi_info(res);
- if (rc != 0) {
- fprintf(stderr, "Volume validation failed: %d\n", rc);
- goto ubigen_create_err;
- }
-
- dump_info(res);
- *u = res;
- return rc;
-
-ubigen_create_err:
- if (res) {
- if (res->v)
- free(res->v);
- if (res->ec)
- free(res->ec);
- if (res->buf)
- free(res->buf);
- free(res);
+ int size = ui->leb_size;
+ struct ubigen_vol_info vi;
+ char outbuf[ui->peb_size];
+ struct ubi_vid_hdr *vid_hdr;
+
+ if (size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE)
+ size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
+
+ vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
+ vi.id = UBI_LAYOUT_VOL_ID;
+ vi.alignment = 1;
+ vi.data_pad = 0;
+ vi.usable_leb_size = ui->leb_size;
+ vi.type = UBI_VID_DYNAMIC;
+ vi.name = UBI_LAYOUT_VOLUME_NAME;
+ vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
+ vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
+
+ memset(outbuf, 0xFF, ui->data_offs);
+ vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+ init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf);
+ memcpy(outbuf + ui->data_offs, vtbl, size);
+ memset(outbuf + ui->data_offs + size, 0xFF,
+ ui->peb_size - ui->data_offs - size);
+
+ init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
+ size = fwrite(outbuf, 1, ui->peb_size, out);
+ if (size == ui->peb_size) {
+ init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
+ size = fwrite(outbuf, 1, ui->peb_size, out);
+ if (size != ui->peb_size) {
+ errmsg("cannot write %d bytes", ui->peb_size);
+ perror("write");
+ return -1;
+ }
}
- *u = NULL;
- return rc;
-}
-
-int
-ubigen_get_leb_size(ubi_info_t u, size_t* size)
-{
- if (u == NULL)
- return -EINVAL;
-
- *size = u->leb_size;
- return 0;
-}
-
-
-int
-ubigen_get_leb_total(ubi_info_t u, size_t* total)
-{
- if (u == NULL)
- return -EINVAL;
-
- *total = u->leb_total;
- return 0;
-}
-
-int
-ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes,
- const char* vol_name, struct ubi_vtbl_record *lvol_rec)
-{
- uint32_t crc;
-
- if ((u == NULL) || (vol_name == NULL))
- return -EINVAL;
-
- memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE);
-
- lvol_rec->reserved_pebs =
- __cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size));
- lvol_rec->alignment = __cpu_to_be32(u->alignment);
- lvol_rec->data_pad = u->v->data_pad;
- lvol_rec->vol_type = u->v->vol_type;
-
- lvol_rec->name_len =
- __cpu_to_be16((uint16_t)strlen((const char*)vol_name));
-
- memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1);
-
- crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
- lvol_rec, UBI_VTBL_RECORD_SIZE_CRC);
- lvol_rec->crc = __cpu_to_be32(crc);
return 0;
}
diff --git a/ubi-utils/src/list.c b/ubi-utils/src/list.c
index 6eb716b..a701158 100644
--- a/ubi-utils/src/list.c
+++ b/ubi-utils/src/list.c
@@ -24,36 +24,30 @@
#include "list.h"
-list_t
-mk_empty(void)
-{
- return (list_t) NULL;
-}
-
int
-is_empty(list_t l)
+is_empty(struct list_entry *l)
{
return l == NULL;
}
info_t
-head(list_t l)
+head(struct list_entry *l)
{
assert(!is_empty(l));
return l->info;
}
-list_t
-tail(list_t l)
+struct list_entry *
+tail(struct list_entry *l)
{
assert(!is_empty(l));
return l->next;
}
-list_t
-remove_head(list_t l)
+struct list_entry *
+remove_head(struct list_entry *l)
{
- list_t res;
+ struct list_entry *res;
assert(!is_empty(l));
res = l->next;
@@ -61,10 +55,10 @@ remove_head(list_t l)
return res;
}
-list_t
-cons(info_t e, list_t l)
+struct list_entry *
+cons(info_t e, struct list_entry *l)
{
- list_t res = malloc(sizeof(*l));
+ struct list_entry *res = malloc(sizeof(*l));
if (!res)
return NULL;
res->info = e;
@@ -73,14 +67,14 @@ cons(info_t e, list_t l)
return res;
}
-list_t
-prepend_elem(info_t e, list_t l)
+struct list_entry *
+prepend_elem(info_t e, struct list_entry *l)
{
return cons(e,l);
}
-list_t
-append_elem(info_t e, list_t l)
+struct list_entry *
+append_elem(info_t e, struct list_entry *l)
{
if (is_empty(l)) {
return cons(e,l);
@@ -90,8 +84,8 @@ append_elem(info_t e, list_t l)
return l;
}
-list_t
-insert_sorted(cmp_func_t cmp, info_t e, list_t l)
+struct list_entry *
+insert_sorted(cmp_func_t cmp, info_t e, struct list_entry *l)
{
if (is_empty(l))
return cons(e, l);
@@ -112,12 +106,12 @@ insert_sorted(cmp_func_t cmp, info_t e, list_t l)
return NULL;
}
-list_t
-remove_all(free_func_t free_func, list_t l)
+struct list_entry *
+remove_all(free_func_t free_func, struct list_entry *l)
{
if (is_empty(l))
return l;
- list_t lnext = l->next;
+ struct list_entry *lnext = l->next;
if (free_func && l->info) {
free_func(&(l->info));
@@ -129,7 +123,7 @@ remove_all(free_func_t free_func, list_t l)
info_t
-is_in(cmp_func_t cmp, info_t e, list_t l)
+is_in(cmp_func_t cmp, info_t e, struct list_entry *l)
{
return
(is_empty(l))
@@ -139,11 +133,11 @@ is_in(cmp_func_t cmp, info_t e, list_t l)
void
-apply(process_func_t process_func, list_t l)
+apply(process_func_t process_func, struct list_entry *l)
{
- list_t ptr;
+ struct list_entry *ptr;
void *i;
- foreach(i, ptr, l) {
+ list_for_each(i, ptr, l) {
process_func(i);
}
}
diff --git a/ubi-utils/src/list.h b/ubi-utils/src/list.h
index e8452a2..58bfe7e 100644
--- a/ubi-utils/src/list.h
+++ b/ubi-utils/src/list.h
@@ -1,5 +1,3 @@
-#ifndef __LIST_H__
-#define __LIST_H__
/*
* Copyright (c) International Business Machines Corp., 2006
*
@@ -20,37 +18,44 @@
* Author: Oliver Lohmann
*/
+#ifndef __UBIUTILS_LIST_H__
+#define __UBIUTILS_LIST_H__
+
#include <stdint.h>
-#define foreach(elem, ptr, list) \
- for (elem = list != NULL ? (typeof(elem)) head(list) \
- : NULL, ptr = list; \
- ptr != NULL; \
- ptr = tail(ptr), \
- elem = (typeof(elem)) ptr ? head(ptr) : NULL)
+#define list_for_each(elem, ptr, list) \
+ for ((elem) = (list) != NULL ? (typeof(elem)) head(list) \
+ : NULL, (ptr) = (list); \
+ ptr != NULL; \
+ ptr = tail(ptr), \
+ elem = (typeof(elem)) (ptr) ? head(ptr) : NULL)
+
+static inline struct list_entry *list_empty(void)
+{
+ return NULL;
+}
-typedef struct node* list_t;
typedef void* info_t;
typedef int (*free_func_t)(info_t*);
typedef int (*cmp_func_t)(info_t, info_t);
typedef void (*process_func_t)(info_t);
-struct node {
- list_t next;
+struct list_entry {
+ struct list_entry *next;
info_t info;
};
-list_t mk_empty(void);
-int is_empty(list_t l);
-info_t is_in(cmp_func_t cmp, info_t e, list_t l);
-info_t head(list_t l);
-list_t tail(list_t l);
-list_t remove_head(list_t l);
-list_t cons(info_t e, list_t l);
-list_t prepend_elem(info_t e, list_t);
-list_t append_elem(info_t e, list_t);
-list_t remove_all(free_func_t free_func, list_t l);
-list_t insert_sorted(cmp_func_t cmp_func, info_t e, list_t l);
-void apply(process_func_t process_func, list_t l);
-
-#endif /* __LIST_H__ */
+struct list_entry *list_empty(void);
+int is_empty(struct list_entry *l);
+info_t is_in(cmp_func_t cmp, info_t e, struct list_entry *l);
+info_t head(struct list_entry *l);
+struct list_entry *tail(struct list_entry *l);
+struct list_entry *remove_head(struct list_entry *l);
+struct list_entry *cons(info_t e, struct list_entry *l);
+struct list_entry *prepend_elem(info_t e, struct list_entry *);
+struct list_entry *append_elem(info_t e, struct list_entry *);
+struct list_entry *remove_all(free_func_t free_func, struct list_entry *l);
+struct list_entry *insert_sorted(cmp_func_t cmp_func, info_t e, struct list_entry *l);
+void apply(process_func_t process_func, struct list_entry *l);
+
+#endif /* !__UBIUTILS_LIST_H__ */
diff --git a/ubi-utils/src/peb.c b/ubi-utils/src/peb.c
deleted file mode 100644
index 160a463..0000000
--- a/ubi-utils/src/peb.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "peb.h"
-
-int
-peb_cmp(peb_t eb_1, peb_t eb_2)
-{
- assert(eb_1);
- assert(eb_2);
-
- return eb_1->num == eb_2->num ? 0
- : eb_1->num > eb_2->num ? 1 : -1;
-}
-
-int
-peb_new(uint32_t eb_num, uint32_t peb_size, peb_t *peb)
-{
- int rc = 0;
-
- peb_t res = (peb_t) malloc(sizeof(struct peb));
- if (!res) {
- rc = -ENOMEM;
- goto err;
- }
-
- res->num = eb_num;
- res->size = peb_size;
- res->data = (uint8_t*) malloc(res->size * sizeof(uint8_t));
- if (!res->data) {
- rc = -ENOMEM;
- goto err;
- }
- memset(res->data, 0xff, res->size);
-
- *peb = res;
- return 0;
-err:
- if (res) {
- if (res->data)
- free(res->data);
- free(res);
- }
- *peb = NULL;
- return rc;
-}
-
-int
-peb_fill(peb_t peb, uint8_t* buf, size_t buf_size)
-{
- if (!peb)
- return -EINVAL;
-
- if (buf_size > peb->size)
- return -EINVAL;
-
- memcpy(peb->data, buf, buf_size);
- return 0;
-}
-
-int
-peb_write(FILE* fp_out, peb_t peb)
-{
- size_t written = 0;
-
- if (peb == NULL)
- return -EINVAL;
-
- written = fwrite(peb->data, 1, peb->size, fp_out);
-
- if (written != peb->size)
- return -EIO;
-
- return 0;
-}
-
-int
-peb_free(peb_t* peb)
-{
- peb_t tmp = *peb;
- if (tmp) {
- if (tmp->data)
- free(tmp->data);
- free(tmp);
- }
- *peb = NULL;
-
- return 0;
-}
-
-void peb_dump(FILE* fp_out, peb_t peb)
-{
- fprintf(fp_out, "num: %08d\tsize: 0x%08x\n", peb->num, peb->size);
-}
diff --git a/ubi-utils/src/peb.h b/ubi-utils/src/peb.h
deleted file mode 100644
index 246bce8..0000000
--- a/ubi-utils/src/peb.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef __RAW_BLOCK_H__
-#define __RAW_BLOCK_H__
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Oliver Lohmann
- */
-
-#include <stdint.h>
-#include <stdio.h>
-
-typedef struct peb *peb_t;
-struct peb {
- uint32_t num; /* Physical eraseblock number
- * in the RAW file. */
- uint32_t size; /* Data Size (equals physical
- * erase block size) */
- uint8_t* data; /* Data buffer */
-};
-
-int peb_new(uint32_t peb_num, uint32_t peb_size, peb_t* peb);
-int peb_free(peb_t* peb);
-int peb_cmp(peb_t peb_1, peb_t peb_2);
-int peb_write(FILE* fp_out, peb_t peb);
-void peb_dump(FILE* fp_out, peb_t peb);
-
-#endif /* __RAW_BLOCK_H__ */
diff --git a/ubi-utils/src/pfi.c b/ubi-utils/src/pfi.c
deleted file mode 100644
index fa835e2..0000000
--- a/ubi-utils/src/pfi.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * @file pfi.c
- *
- * @author Oliver Lohmann
- * Andreas Arnez
- * Joern Engel
- * Frank Haverkamp
- *
- * @brief libpfi holds all code to create and process pfi files.
- *
- * <oliloh@de.ibm.com> Wed Feb 8 11:38:22 CET 2006: Initial creation.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <syslog.h>
-#include <stdarg.h>
-#include <errno.h>
-
-#include "pfi.h"
-
-#define PFI_MAGIC "PFI!\n"
-#define PFI_DATA "DATA\n" /* The same size as PFI_MAGIC */
-#define PFI_MAGIC_LEN 5
-
-static const char copyright [] __attribute__((unused)) =
- "Copyright (c) International Business Machines Corp., 2006";
-
-enum key_id {
- /* version 1 */
- key_version, /* must be index position 0! */
- key_mode,
- key_size,
- key_crc,
- key_label,
- key_flags,
- key_ubi_ids,
- key_ubi_size,
- key_ubi_type,
- key_ubi_names,
- key_ubi_alignment,
- key_raw_starts,
- key_raw_total_size,
- num_keys,
-};
-
-struct pfi_header {
- char defined[num_keys]; /* reserve all possible keys even if
- version does not require this. */
- int mode_no; /* current mode no. -> can only increase */
- union {
- char *str;
- uint32_t num;
- } value[num_keys];
-};
-
-
-#define PFI_MANDATORY 0x0001
-#define PFI_STRING 0x0002
-#define PFI_LISTVALUE 0x0004 /* comma seperated list of nums */
-#define PFI_MANDATORY_UBI 0x0008
-#define PFI_MANDATORY_RAW 0x0010
-
-struct key_descriptor {
- enum key_id id;
- const char *name;
- uint32_t flags;
-};
-
-static const struct key_descriptor key_desc_v1[] = {
- { key_version, "version", PFI_MANDATORY },
- { key_mode, "mode", PFI_MANDATORY | PFI_STRING },
- { key_size, "size", PFI_MANDATORY },
- { key_crc, "crc", PFI_MANDATORY },
- { key_label, "label", PFI_MANDATORY | PFI_STRING },
- { key_flags, "flags", PFI_MANDATORY },
- { key_ubi_ids, "ubi_ids", PFI_MANDATORY_UBI | PFI_STRING },
- { key_ubi_size, "ubi_size", PFI_MANDATORY_UBI },
- { key_ubi_type, "ubi_type", PFI_MANDATORY_UBI | PFI_STRING },
- { key_ubi_names, "ubi_names", PFI_MANDATORY_UBI | PFI_STRING },
- { key_ubi_alignment, "ubi_alignment", PFI_MANDATORY_UBI },
- { key_raw_starts, "raw_starts", PFI_MANDATORY_RAW | PFI_STRING },
- { key_raw_total_size, "raw_total_size", PFI_MANDATORY_RAW },
-};
-
-static const struct key_descriptor *key_descriptors[] = {
- NULL,
- key_desc_v1, /* version 1 */
-};
-
-static const int key_descriptors_max[] = {
- 0, /* version 0 */
- sizeof(key_desc_v1)/sizeof(struct key_descriptor), /* version 1 */
-};
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-static const char* modes[] = {"raw", "ubi"}; /* order isn't arbitrary! */
-
-/* latest version contains all possible keys */
-static const struct key_descriptor *key_desc = key_desc_v1;
-
-#define PFI_IS_UBI(mode) \
- (((mode) != NULL) && (strcmp("ubi", (mode)) == 0))
-
-#define PFI_IS_RAW(mode) \
- (((mode) != NULL) && (strcmp("raw", (mode)) == 0))
-
-/**
- * @return <0 On Error.
- * >=0 Mode no.
- */
-static int
-get_mode_no(const char* mode)
-{
- int i;
-
- for (i = 0; i < (int)ARRAY_SIZE(modes); i++)
- if (strcmp(mode, modes[i]) == 0)
- return i;
- return -1;
-}
-
-static int
-find_key_by_name (const char *name)
-{
- int i;
-
- for (i = 0; i < num_keys; i++) {
- if (strcmp(name, key_desc[i].name) == 0)
- return i;
- }
- return -1;
-}
-
-static int
-check_valid (pfi_header head)
-{
- int i;
- int max_keys;
- uint32_t version;
- const char *mode;
- const struct key_descriptor *desc;
- uint32_t to_check = PFI_MANDATORY;
-
- /*
- * For the validity check the list of possible keys depends on
- * the version of the PFI file used.
- */
- version = head->value[key_version].num;
- if (version > PFI_HDRVERSION)
- return PFI_ENOHEADER;
-
- max_keys = key_descriptors_max[version];
- desc = key_descriptors[version];
-
- if (!desc)
- return PFI_ENOVERSION;
-
- mode = head->value[key_mode].str;
- if (PFI_IS_UBI(mode)) {
- to_check |= PFI_MANDATORY_UBI;
- }
- else if (PFI_IS_RAW(mode)) {
- to_check |= PFI_MANDATORY_RAW;
- }
- else { /* neither UBI nor RAW == ERR */
- return PFI_EINSUFF;
- }
-
- for (i = 0; i < max_keys; i++) {
- if ((desc[i].flags & to_check) && !head->defined[i]) {
- fprintf(stderr, "libpfi: %s missing\n", desc[i].name);
- return PFI_EINSUFF;
- }
- }
-
- return 0;
-}
-
-int pfi_header_init (pfi_header *head)
-{
- int i;
- pfi_header self = (pfi_header) malloc(sizeof(*self));
-
- *head = self;
- if (self == NULL)
- return PFI_ENOMEM;
-
- /* initialize maximum number of possible keys */
- for (i = 0; i < num_keys; i++) {
- memset(self, 0, sizeof(*self));
- self->defined[i] = 0;
- }
-
- return 0;
-}
-
-int pfi_header_destroy (pfi_header *head)
-{
- int i;
- pfi_header self = *head;
-
- for (i = 0; i < num_keys; i++) {
- if (self->defined[i] && (key_desc[i].flags & PFI_STRING) &&
- self->value[i].str) {
- free(self->value[i].str);
- }
- }
- free(*head);
- *head = NULL;
- return 0;
-}
-
-int pfi_header_setnumber (pfi_header head,
- const char *key, uint32_t value)
-{
- int key_id = find_key_by_name(key);
-
- if (key_id < 0)
- return PFI_EUNDEF;
-
- if (key_desc[key_id].flags & PFI_STRING)
- return PFI_EBADTYPE;
-
- head->value[key_id].num = value;
- head->defined[key_id] = 1;
- return 0;
-}
-
-int pfi_header_setvalue (pfi_header head,
- const char *key, const char *value)
-{
- int key_id = find_key_by_name(key);
-
- if (value == NULL)
- return PFI_EINSUFF;
-
- if ((key_id < 0) || (key_id >= num_keys))
- return PFI_EUNDEF;
-
- if (key_desc[key_id].flags & PFI_STRING) {
- /*
- * The value is a string. Copy to a newly allocated
- * buffer. Delete the old value, if already set.
- */
- size_t len = strlen(value) + 1;
- char *old_str = NULL;
- char *str;
-
- old_str = head->value[key_id].str;
- if (old_str != NULL)
- free(old_str);
-
- str = head->value[key_id].str = (char *) malloc(len);
- if (str == NULL)
- return PFI_ENOMEM;
-
- strcpy(str, value);
- } else {
- int len;
- int ret;
- /* FIXME: here we assume that the value is always
- given in hex and starts with '0x'. */
- ret = sscanf(value, "0x%x%n", &head->value[key_id].num, &len);
- if (ret < 1 || value[len] != '\0')
- return PFI_EBADTYPE;
- }
- head->defined[key_id] = 1;
- return 0;
-}
-
-int pfi_header_getnumber (pfi_header head,
- const char *key, uint32_t *value)
-{
- int key_id = find_key_by_name(key);
-
- if (key_id < 0)
- return PFI_EUNDEF;
-
- if (key_desc[key_id].flags & PFI_STRING)
- return PFI_EBADTYPE;
-
- if (!head->defined[key_id])
- return PFI_EUNDEF;
-
- *value = head->value[key_id].num;
- return 0;
-}
-
-int pfi_header_getstring (pfi_header head,
- const char *key, char *value, size_t size)
-{
- int key_id = find_key_by_name(key);
-
- if (key_id < 0)
- return PFI_EUNDEF;
-
- if (!(key_desc[key_id].flags & PFI_STRING))
- return PFI_EBADTYPE;
-
- if (!head->defined[key_id])
- return PFI_EUNDEF;
-
- strncpy(value, head->value[key_id].str, size-1);
- value[size-1] = '\0';
- return 0;
-}
-
-int pfi_header_write (FILE *out, pfi_header head)
-{
- int i;
- int ret;
-
- pfi_header_setnumber(head, "version", PFI_HDRVERSION);
-
- if ((ret = check_valid(head)) != 0)
- return ret;
-
- /* OK. Now write the header. */
-
- ret = fwrite(PFI_MAGIC, 1, PFI_MAGIC_LEN, out);
- if (ret < PFI_MAGIC_LEN)
- return ret;
-
-
- for (i = 0; i < num_keys; i++) {
- if (!head->defined[i])
- continue;
-
- ret = fprintf(out, "%s=", key_desc[i].name);
- if (ret < 0)
- return PFI_EFILE;
-
- if (key_desc[i].flags & PFI_STRING) {
- ret = fprintf(out, "%s", head->value[i].str);
- if (ret < 0)
- return PFI_EFILE;
- } else {
- ret = fprintf(out, "0x%8x", head->value[i].num);
- if (ret < 0)
- return PFI_EFILE;
-
- }
- ret = fprintf(out, "\n");
- if (ret < 0)
- return PFI_EFILE;
- }
- ret = fprintf(out, "\n");
- if (ret < 0)
- return PFI_EFILE;
-
- ret = fflush(out);
- if (ret != 0)
- return PFI_EFILE;
-
- return 0;
-}
-
-int pfi_header_read (FILE *in, pfi_header head)
-{
- char magic[PFI_MAGIC_LEN];
- char mode[PFI_KEYWORD_LEN];
- char buf[256];
-
- if (PFI_MAGIC_LEN != fread(magic, 1, PFI_MAGIC_LEN, in))
- return PFI_EFILE;
- if (memcmp(magic, PFI_MAGIC, PFI_MAGIC_LEN) != 0) {
- if (memcmp(magic, PFI_DATA, PFI_MAGIC_LEN) == 0) {
- return PFI_DATA_START;
- }
- return PFI_ENOHEADER;
- }
-
- while (fgets(buf, sizeof(buf), in) != NULL && buf[0] != '\n') {
- char *value;
- char *end;
- value = strchr(buf, '=');
- if (value == NULL)
- return PFI_ENOHEADER;
-
- *value = '\0';
- value++;
- end = strchr(value, '\n');
- if (end)
- *end = '\0';
-
- if (pfi_header_setvalue(head, buf, value))
- return PFI_ENOHEADER;
- }
-
- if (check_valid(head) != 0)
- return PFI_ENOHEADER;
-
- /* set current mode no. in head */
- pfi_header_getstring(head, "mode", mode, PFI_KEYWORD_LEN);
- if (head->mode_no > get_mode_no(mode)) {
- return PFI_EMODE;
- }
- head->mode_no = get_mode_no(mode);
- return 0;
-}
-
-int pfi_header_dump (FILE *out, pfi_header head __attribute__((__unused__)))
-{
- fprintf(out, "Sorry not implemented yet. Write mail to "
- "Andreas Arnez and complain!\n");
- return 0;
-}
-
-int pfi_read (FILE *in, pfi_read_func func, void *priv_data)
-{
- int rc;
- pfi_header header;
-
- rc = pfi_header_init (&header);
- if (0 != rc)
- return rc;
- if (!func)
- return PFI_EINVAL;
-
- while ((0 == rc) && !feof(in)) {
- /*
- * Read header and check consistency of the fields.
- */
- rc = pfi_header_read( in, header );
- if (0 != rc)
- break;
- if (func) {
- rc = func(in, header, priv_data);
- if (rc != 0)
- break;
- }
- }
-
- pfi_header_destroy(&header);
- return rc;
-}
diff --git a/ubi-utils/src/pfi2bin.c b/ubi-utils/src/pfi2bin.c
index cacf33f..4289fca 100644
--- a/ubi-utils/src/pfi2bin.c
+++ b/ubi-utils/src/pfi2bin.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) International Business Machines Corp., 2006
- * Copyright (C) 2007 Nokia Corporation
+ * Copyright (C) 2008 Nokia Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,29 +30,21 @@
*/
#include <stdlib.h>
-#include <stdint.h>
#include <getopt.h>
#include <stdio.h>
#include <string.h>
-#include <assert.h>
#include <errno.h>
+#include <unistd.h>
-#include <ubigen.h>
#include <mtd/ubi-header.h>
+#include <libubigen.h>
+#include <libpfi.h>
#include "common.h"
#include "list.h"
-#include "reader.h"
-#include "peb.h"
-#include "crc32.h"
#define PROGRAM_VERSION "1.5"
#define PROGRAM_NAME "pfi2bin"
-#define ERR_BUF_SIZE 1024
-
-static uint32_t crc32_table[256];
-static char err_buf[ERR_BUF_SIZE];
-
static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
" - a tool to convert PFI files into raw flash images. Note, if not\n"
"sure about some of the parameters, do not specify them and let the utility to\n"
@@ -269,386 +261,110 @@ static int parse_opt(int argc, char * const argv[])
return 0;
}
-
-static size_t
-byte_to_blk(size_t byte, size_t blk_size)
-{
- return (byte % blk_size) == 0
- ? byte / blk_size
- : byte / blk_size + 1;
-}
-
-
-
-
/**
- * @precondition IO: File stream points to first byte of RAW data.
- * @postcondition IO: File stream points to first byte of next
- * or EOF.
+ * pfi2vol_info - convert PFI UBI volume information to libubigen.
+ * @pfi: PFI UBI volume information
+ * @n: PFI volume index to convert
+ * @vi: libubigen volume information
*/
-static int
-memorize_raw_eb(pfi_raw_t pfi_raw, list_t *raw_pebs)
-{
- int err = 0;
- int i, read, to_read, eb_num, bytes_left;
- list_t pebs = *raw_pebs;
- peb_t peb = NULL;
-
- long old_file_pos = ftell(args.fp_in);
- for (i = 0; i < (int)pfi_raw->starts_size; i++) {
- bytes_left = pfi_raw->data_size;
- err = fseek(args.fp_in, old_file_pos, SEEK_SET);
- if (err != 0)
- goto err;
-
- eb_num = byte_to_blk(pfi_raw->starts[i], args.peb_size);
- while (bytes_left) {
- to_read = MIN(bytes_left, args.peb_size);
- err = peb_new(eb_num++, args.peb_size, &peb);
- if (err != 0)
- goto err;
- read = fread(peb->data, 1, to_read, args.fp_in);
- if (read != to_read) {
- err = -EIO;
- goto err;
- }
- pebs = append_elem(peb, pebs);
- bytes_left -= read;
- }
-
- }
- *raw_pebs = pebs;
- return 0;
-err:
- pebs = remove_all((free_func_t)&peb_free, pebs);
- return err;
-}
-
-static int
-convert_ubi_volume(pfi_ubi_t ubi, list_t raw_pebs,
- struct ubi_vtbl_record *vol_tab,
- size_t *ebs_written)
+static void pfi2vol_info(const struct pfi_ubi *pfi, int n,
+ struct ubigen_vol_info *vi,
+ const struct ubigen_info *ui)
{
- int err = 0;
- uint32_t i, j;
- peb_t raw_peb;
- peb_t cmp_peb;
- ubi_info_t u;
- size_t leb_total = 0;
- uint8_t vol_type;
-
- switch (ubi->type) {
- case pfi_ubi_static:
- vol_type = UBI_VID_STATIC; break;
- case pfi_ubi_dynamic:
- vol_type = UBI_VID_DYNAMIC; break;
- default:
- vol_type = UBI_VID_DYNAMIC;
- }
-
- err = peb_new(0, 0, &cmp_peb);
- if (err != 0)
- goto err;
-
- long old_file_pos = ftell(args.fp_in);
- for (i = 0; i < ubi->ids_size; i++) {
- err = fseek(args.fp_in, old_file_pos, SEEK_SET);
- if (err != 0)
- goto err;
- err = ubigen_create(&u, ubi->ids[i], vol_type,
- args.peb_size, args.ec,
- ubi->alignment, args.ubi_ver,
- args.vid_hdr_offs, 0, ubi->data_size,
- args.fp_in, args.fp_out);
- if (err != 0)
- goto err;
-
- err = ubigen_get_leb_total(u, &leb_total);
- if (err != 0)
- goto err;
-
- j = 0;
- while(j < leb_total) {
- cmp_peb->num = *ebs_written;
- raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb,
- raw_pebs);
- if (raw_peb) {
- err = peb_write(args.fp_out, raw_peb);
- }
- else {
- err = ubigen_write_leb(u, NO_ERROR);
- j++;
- }
- if (err != 0)
- goto err;
- (*ebs_written)++;
- }
- /* memorize volume table entry */
- err = ubigen_set_lvol_rec(u, ubi->size,
- ubi->names[i],
- (void*) &vol_tab[ubi->ids[i]]);
- if (err != 0)
- goto err;
- ubigen_destroy(&u);
+ vi->id = pfi->ids[n];
+ vi->bytes = pfi->size;
+ vi->alignment = pfi->alignment;
+ vi->data_pad = ui->leb_size % vi->alignment;
+ vi->usable_leb_size = ui->leb_size - vi->data_pad;
+ vi->type = pfi->vol_type;
+ vi->name = pfi->names[n];
+ vi->name_len = strlen(vi->name);
+ if (vi->name_len > UBI_VOL_NAME_MAX) {
+ errmsg("too long name, cut to %d symbols: \"%s\"",
+ UBI_VOL_NAME_MAX, vi->name);
+ vi->name_len = UBI_VOL_NAME_MAX;
}
- peb_free(&cmp_peb);
- return 0;
-
-err:
- peb_free(&cmp_peb);
- ubigen_destroy(&u);
- return err;
-}
-
-
-static FILE*
-my_fmemopen (void *buf, size_t size, const char *opentype)
-{
- FILE* f;
- size_t ret;
-
- assert(strcmp(opentype, "r") == 0);
-
- f = tmpfile();
- ret = fwrite(buf, 1, size, f);
- rewind(f);
-
- return f;
+ vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size;
+ vi->compat = 0;
}
-/**
- * @brief Builds a UBI volume table from a volume entry list.
- * @return 0 On success.
- * else Error.
- */
-static int
-write_ubi_volume_table(list_t raw_pebs,
- struct ubi_vtbl_record *vol_tab, size_t vol_tab_size,
- size_t *ebs_written)
+static int create_flash_image(void)
{
- int err = 0;
- ubi_info_t u;
- peb_t raw_peb;
- peb_t cmp_peb;
- size_t leb_size, leb_total, j = 0;
- uint8_t *ptr = NULL;
- FILE* fp_leb = NULL;
- int vt_slots;
- size_t vol_tab_size_limit;
-
- err = peb_new(0, 0, &cmp_peb);
- if (err != 0)
- goto err;
-
- /* @FIXME: Artem creates one volume with 2 LEBs.
- * IMO 2 volumes would be more convenient. In order
- * to get 2 reserved LEBs from ubigen, I have to
- * introduce this stupid mechanism. Until no final
- * decision of the VTAB structure is made... Good enough.
- */
- err = ubigen_create(&u, UBI_LAYOUT_VOL_ID, UBI_VID_DYNAMIC,
- args.peb_size, args.ec,
- 1, args.ubi_ver,
- args.vid_hdr_offs, UBI_COMPAT_REJECT,
- vol_tab_size, stdin, args.fp_out);
- /* @FIXME stdin for fp_in is a hack */
- if (err != 0)
- goto err;
- err = ubigen_get_leb_size(u, &leb_size);
- if (err != 0)
- goto err;
- ubigen_destroy(&u);
-
- /*
- * The number of supported volumes is restricted by the eraseblock size
- * and by the UBI_MAX_VOLUMES constant.
- */
- vt_slots = leb_size / UBI_VTBL_RECORD_SIZE;
- if (vt_slots > UBI_MAX_VOLUMES)
- vt_slots = UBI_MAX_VOLUMES;
- vol_tab_size_limit = vt_slots * UBI_VTBL_RECORD_SIZE;
-
- ptr = (uint8_t*) malloc(leb_size * sizeof(uint8_t));
- if (ptr == NULL)
- goto err;
-
- memset(ptr, 0xff, leb_size);
- memcpy(ptr, vol_tab, vol_tab_size_limit);
- fp_leb = my_fmemopen(ptr, leb_size, "r");
-
- err = ubigen_create(&u, UBI_LAYOUT_VOL_ID, UBI_VID_DYNAMIC,
- args.peb_size, args.ec,
- 1, args.ubi_ver, args.vid_hdr_offs,
- UBI_COMPAT_REJECT, leb_size * UBI_LAYOUT_VOLUME_EBS,
- fp_leb, args.fp_out);
- if (err != 0)
- goto err;
- err = ubigen_get_leb_total(u, &leb_total);
- if (err != 0)
- goto err;
-
- long old_file_pos = ftell(fp_leb);
- while(j < leb_total) {
- err = fseek(fp_leb, old_file_pos, SEEK_SET);
- if (err != 0)
- goto err;
-
- cmp_peb->num = *ebs_written;
- raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb,
- raw_pebs);
- if (raw_peb) {
- err = peb_write(args.fp_out, raw_peb);
- }
- else {
- err = ubigen_write_leb(u, NO_ERROR);
- j++;
- }
-
- if (err != 0)
- goto err;
- (*ebs_written)++;
- }
-
-err:
- free(ptr);
- peb_free(&cmp_peb);
- ubigen_destroy(&u);
- fclose(fp_leb);
- return err;
-}
-
-static int
-write_remaining_raw_ebs(list_t raw_blocks, size_t *ebs_written,
- FILE* fp_out)
-{
- int err = 0;
- uint32_t j, delta;
- list_t ptr;
- peb_t empty_eb, peb;
-
- /* create an empty 0xff EB (for padding) */
- err = peb_new(0, args.peb_size, &empty_eb);
-
- foreach(peb, ptr, raw_blocks) {
- if (peb->num < *ebs_written) {
- continue; /* omit blocks which
- are already passed */
- }
-
- if (peb->num < *ebs_written) {
- errmsg("eb_num: %d\n", peb->num);
- errmsg("Bug: This should never happen. %d %s",
- __LINE__, __FILE__);
- goto err;
- }
-
- delta = peb->num - *ebs_written;
- for (j = 0; j < delta; j++) {
- err = peb_write(fp_out, empty_eb);
- if (err != 0)
- goto err;
- (*ebs_written)++;
- }
- err = peb_write(fp_out, peb);
- if (err != 0)
- goto err;
- (*ebs_written)++;
+ int i, err, vtbl_size = args.peb_size;
+ struct ubigen_info ui;
+ struct list_entry *ubi_list = list_empty(), *ptr;
+ struct ubi_vtbl_record *vtbl;
+ struct pfi_ubi *pfi;
+
+ vtbl = ubigen_create_empty_vtbl(&vtbl_size);
+ if (!vtbl) {
+ errmsg("cannot initialize volume table");
+ return -1;
}
-err:
- peb_free(&empty_eb);
- return err;
-}
-
-static int
-init_vol_tab(struct ubi_vtbl_record **vol_tab, size_t *vol_tab_size)
-{
- uint32_t crc;
- size_t i;
- struct ubi_vtbl_record* res = NULL;
-
- *vol_tab_size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE;
+ ubigen_info_init(&ui, args.peb_size, args.min_io_size,
+ args.subpage_size, args.vid_hdr_offs, args.ubi_ver,
+ args.ec);
- res = (struct ubi_vtbl_record*) calloc(1, *vol_tab_size);
- if (vol_tab == NULL) {
- return -ENOMEM;
+ err = read_pfi_headers(&ubi_list, args.fp_in);
+ if (err != 0) {
+ errmsg("cannot read PFI headers, error %d", err);
+ goto error;
}
- for (i = 0; i < UBI_MAX_VOLUMES; i++) {
- crc = clc_crc32(crc32_table, UBI_CRC32_INIT,
- &(res[i]), UBI_VTBL_RECORD_SIZE_CRC);
- res[i].crc = __cpu_to_be32(crc);
- }
+ /* Add all volumes to the volume table */
+ list_for_each(pfi, ptr, ubi_list)
+ for (i = 0; i < pfi->ids_size; i++) {
+ struct ubigen_vol_info vi;
- *vol_tab = res;
- return 0;
-}
-
-static int
-create_raw(void)
-{
- int err = 0;
- size_t ebs_written = 0; /* eraseblocks written already... */
- size_t vol_tab_size;
- list_t ptr;
-
- list_t pfi_raws = mk_empty(); /* list of raw sections from a pfi */
- list_t pfi_ubis = mk_empty(); /* list of ubi sections from a pfi */
- list_t raw_pebs = mk_empty(); /* list of raw eraseblocks */
-
- struct ubi_vtbl_record *vol_tab = NULL;
+ pfi2vol_info(pfi, i, &vi, &ui);
+ ubigen_add_volume(&ui, &vi, vtbl);
+ }
- err = init_vol_tab (&vol_tab, &vol_tab_size);
- if (err != 0) {
- errmsg("cannot initialize volume table");
- goto err;
+ err = ubigen_write_layout_vol(&ui, vtbl, args.fp_out);
+ if (err) {
+ errmsg("cannot create layout volume");
+ goto error;
}
- err = read_pfi_headers(&pfi_raws, &pfi_ubis, args.fp_in,
- err_buf, ERR_BUF_SIZE);
- if (err != 0) {
- errmsg("cannot read pfi header: %s err: %d", err_buf, err);
- goto err;
- }
+ /* Write all volumes */
+ list_for_each(pfi, ptr, ubi_list)
+ for (i = 0; i < pfi->ids_size; i++) {
+ struct ubigen_vol_info vi;
+
+ pfi2vol_info(pfi, i, &vi, &ui);
+ err = fseek(args.fp_in, pfi->data_offs, SEEK_SET);
+ if (err == -1) {
+ errmsg("cannot seek input file");
+ perror("fseek");
+ goto error;
+ }
- pfi_raw_t pfi_raw;
- foreach(pfi_raw, ptr, pfi_raws) {
- err = memorize_raw_eb(pfi_raw, &raw_pebs);
- if (err != 0) {
- errmsg("cannot create raw_block in mem. err: %d\n", err);
- goto err;
+ err = ubigen_write_volume(&ui, &vi, pfi->data_size,
+ args.fp_in, args.fp_out);
+ if (err) {
+ errmsg("cannot write volume %d", vi.id);
+ goto error;
+ }
}
- }
- pfi_ubi_t pfi_ubi;
- foreach(pfi_ubi, ptr, pfi_ubis) {
- err = convert_ubi_volume(pfi_ubi, raw_pebs,
- vol_tab, &ebs_written);
- if (err != 0) {
- errmsg("cannot convert UBI volume. err: %d\n", err);
- goto err;
+ if (args.fp_out != stdout) {
+ i = ftell(args.fp_out);
+ if (i == -1) {
+ errmsg("cannot seek output file");
+ perror("ftell");
+ goto error;
}
- }
- err = write_ubi_volume_table(raw_pebs, vol_tab, vol_tab_size,
- &ebs_written);
- if (err != 0) {
- errmsg("cannot write UBI volume table. err: %d\n", err);
- goto err;
+ printf("physical eraseblocks written: %d (", i / ui.peb_size);
+ ubiutils_print_bytes(i, 0);
+ printf(")\n");
}
- err = write_remaining_raw_ebs(raw_pebs, &ebs_written, args.fp_out);
- if (err != 0)
- goto err;
-
- if (args.fp_out != stdout)
- printf("Physical eraseblocks written: %8d\n", ebs_written);
-err:
- free(vol_tab);
- pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws);
- pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis);
- raw_pebs = remove_all((free_func_t)&peb_free, raw_pebs);
+error:
+ free(vtbl);
+ ubi_list = remove_all((free_func_t)&free_pfi_ubi, ubi_list);
return err;
}
@@ -660,17 +376,8 @@ int main(int argc, char * const argv[])
if (err)
return -1;
- ubigen_init();
- init_crc32_table(crc32_table);
-
- err = create_raw();
- if (err != 0) {
- errmsg("creating RAW failed");
- goto err;
- }
-
-err:
- if (err != 0)
+ err = create_flash_image();
+ if (err)
remove(args.f_out);
return err;
diff --git a/ubi-utils/src/reader.c b/ubi-utils/src/reader.c
deleted file mode 100644
index 0ea8c6d..0000000
--- a/ubi-utils/src/reader.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Oliver Lohmann
- *
- * Read in PFI (partial flash image) data and store it into internal
- * data structures for further processing. Take also care about
- * special handling if the data contains PDD (platform description
- * data/boot-parameters).
- */
-
-#include <string.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "bootenv.h"
-#include "reader.h"
-
-#define __unused __attribute__((unused))
-
-/* @FIXME hard coded offsets right now - get them from Artem? */
-#define NAND2048_DEFAULT_VID_HDR_OFF 1984
-#define NAND512_DEFAULT_VID_HDR_OFF 448
-#define NOR_DEFAULT_VID_HDR_OFF 64
-
-#define EBUF_PFI(fmt...) \
- do { int i = snprintf(err_buf, err_buf_size, "%s\n", label); \
- snprintf(err_buf + i, err_buf_size - i, fmt); \
- } while (0)
-
-#define EBUF(fmt...) \
- do { snprintf(err_buf, err_buf_size, fmt); } while (0)
-
-
-int
-read_pdd_data(FILE* fp_pdd, pdd_data_t* pdd_data,
- char* err_buf, size_t err_buf_size)
-{
- int rc = 0;
- bootenv_t pdd = NULL;
- pdd_data_t res = NULL;
- const char* value;
-
- res = (pdd_data_t) malloc(sizeof(struct pdd_data));
- if (!res) {
- rc = -ENOMEM;
- goto err;
- }
- rc = bootenv_create(&pdd);
- if (rc != 0) {
- goto err;
- }
- rc = bootenv_read_txt(fp_pdd, pdd);
- if (rc != 0) {
- goto err;
- }
- rc = bootenv_get(pdd, "flash_type", &value);
- if (rc != 0) {
- goto err;
- }
-
- if (strcmp(value, "NAND") == 0) {
-
- rc = bootenv_get_num(pdd, "flash_page_size",
- &(res->flash_page_size));
- if (rc != 0) {
- EBUF("Cannot read 'flash_page_size' from pdd.");
- goto err;
- }
- res->flash_type = NAND_FLASH;
-
- switch (res->flash_page_size) {
- case 512:
- res->vid_hdr_offset = NAND512_DEFAULT_VID_HDR_OFF;
- break;
- case 2048:
- res->vid_hdr_offset = NAND2048_DEFAULT_VID_HDR_OFF;
- break;
- default:
- EBUF("Unsupported 'flash_page_size' %d.",
- res->flash_page_size);
- goto err;
- }
- }
- else if (strcmp(value, "NOR") == 0){
- res->flash_type = NOR_FLASH;
- res->vid_hdr_offset = NOR_DEFAULT_VID_HDR_OFF;
- }
- else {
- snprintf(err_buf, err_buf_size,
- "Unkown flash type: %s", value);
- goto err;
- }
-
- rc = bootenv_get_num(pdd, "flash_eraseblock_size",
- &(res->eb_size));
- if (rc != 0) {
- EBUF("Cannot read 'flash_eraseblock_size' from pdd.");
- goto err;
- }
-
- rc = bootenv_get_num(pdd, "flash_size",
- &(res->flash_size));
- if (rc != 0) {
- EBUF("Cannot read 'flash_size' from pdd.");
- goto err;
- }
-
- goto out;
- err:
- if (res) {
- free(res);
- res = NULL;
- }
- out:
- bootenv_destroy(&pdd);
- *pdd_data = res;
- return rc;
-}
-
-int
-read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_raw_t* pfi_raw,
- const char* label, char* err_buf, size_t err_buf_size)
-{
- int rc = 0;
- char tmp_str[PFI_KEYWORD_LEN];
- bootenv_list_t raw_start_list = NULL;
- pfi_raw_t res;
- size_t size;
-
- res = (pfi_raw_t) malloc(sizeof(struct pfi_raw));
- if (!res)
- return -ENOMEM;
-
- rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size));
- if (rc != 0) {
- EBUF_PFI("Cannot read 'size' from PFI.");
- goto err;
- }
-
- rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc));
- if (rc != 0) {
- EBUF_PFI("Cannot read 'crc' from PFI.");
- goto err;
- }
-
- rc = pfi_header_getstring(pfi_hd, "raw_starts",
- tmp_str, PFI_KEYWORD_LEN);
- if (rc != 0) {
- EBUF_PFI("Cannot read 'raw_starts' from PFI.");
- goto err;
- }
-
- rc = bootenv_list_create(&raw_start_list);
- if (rc != 0) {
- goto err;
- }
-
- rc = bootenv_list_import(raw_start_list, tmp_str);
- if (rc != 0) {
- EBUF_PFI("Cannot translate PFI value: %s", tmp_str);
- goto err;
- }
-
- rc = bootenv_list_to_num_vector(raw_start_list,
- &size, &(res->starts));
- res->starts_size = size;
-
- if (rc != 0) {
- EBUF_PFI("Cannot create numeric value array: %s", tmp_str);
- goto err;
- }
-
- goto out;
-
- err:
- if (res) {
- free(res);
- res = NULL;
- }
- out:
- bootenv_list_destroy(&raw_start_list);
- *pfi_raw = res;
- return rc;
-}
-
-int
-read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi __unused, pfi_ubi_t* pfi_ubi,
- const char *label, char* err_buf, size_t err_buf_size)
-{
- int rc = 0;
- const char** tmp_names = NULL;
- char tmp_str[PFI_KEYWORD_LEN];
- bootenv_list_t ubi_id_list = NULL;
- bootenv_list_t ubi_name_list = NULL;
- pfi_ubi_t res;
- uint32_t i;
- size_t size;
-
- res = (pfi_ubi_t) calloc(1, sizeof(struct pfi_ubi));
- if (!res)
- return -ENOMEM;
-
- rc = pfi_header_getnumber(pfi_hd, "size", &(res->data_size));
- if (rc != 0) {
- EBUF_PFI("Cannot read 'size' from PFI.");
- goto err;
- }
-
- rc = pfi_header_getnumber(pfi_hd, "crc", &(res->crc));
- if (rc != 0) {
- EBUF_PFI("Cannot read 'crc' from PFI.");
- goto err;
- }
-
- rc = pfi_header_getstring(pfi_hd, "ubi_ids", tmp_str, PFI_KEYWORD_LEN);
- if (rc != 0) {
- EBUF_PFI("Cannot read 'ubi_ids' from PFI.");
- goto err;
- }
-
- rc = bootenv_list_create(&ubi_id_list);
- if (rc != 0) {
- goto err;
- }
- rc = bootenv_list_create(&ubi_name_list);
- if (rc != 0) {
- goto err;
- }
-
- rc = bootenv_list_import(ubi_id_list, tmp_str);
- if (rc != 0) {
- EBUF_PFI("Cannot translate PFI value: %s", tmp_str);
- goto err;
- }
-
- rc = bootenv_list_to_num_vector(ubi_id_list, &size,
- &(res->ids));
- res->ids_size = size;
- if (rc != 0) {
- EBUF_PFI("Cannot create numeric value array: %s", tmp_str);
- goto err;
- }
-
- if (res->ids_size == 0) {
- rc = -1;
- EBUF_PFI("Sanity check failed: No ubi_ids specified.");
- goto err;
- }
-
- rc = pfi_header_getstring(pfi_hd, "ubi_type",
- tmp_str, PFI_KEYWORD_LEN);
- if (rc != 0) {
- EBUF_PFI("Cannot read 'ubi_type' from PFI.");
- goto err;
- }
- if (strcmp(tmp_str, "static") == 0)
- res->type = pfi_ubi_static;
- else if (strcmp(tmp_str, "dynamic") == 0)
- res->type = pfi_ubi_dynamic;
- else {
- EBUF_PFI("Unknown ubi_type in PFI.");
- goto err;
- }
-
- rc = pfi_header_getnumber(pfi_hd, "ubi_alignment", &(res->alignment));
- if (rc != 0) {
- EBUF_PFI("Cannot read 'ubi_alignment' from PFI.");
- goto err;
- }
-
- rc = pfi_header_getnumber(pfi_hd, "ubi_size", &(res->size));
- if (rc != 0) {
- EBUF_PFI("Cannot read 'ubi_size' from PFI.");
- goto err;
- }
-
- rc = pfi_header_getstring(pfi_hd, "ubi_names",
- tmp_str, PFI_KEYWORD_LEN);
- if (rc != 0) {
- EBUF_PFI("Cannot read 'ubi_names' from PFI.");
- goto err;
- }
-
- rc = bootenv_list_import(ubi_name_list, tmp_str);
- if (rc != 0) {
- EBUF_PFI("Cannot translate PFI value: %s", tmp_str);
- goto err;
- }
- rc = bootenv_list_to_vector(ubi_name_list, &size,
- &(tmp_names));
- res->names_size = size;
- if (rc != 0) {
- EBUF_PFI("Cannot create string array: %s", tmp_str);
- goto err;
- }
-
- if (res->names_size != res->ids_size) {
- EBUF_PFI("Sanity check failed: ubi_ids list does not match "
- "sizeof ubi_names list.");
- rc = -1;
- }
-
- /* copy tmp_names to own structure */
- res->names = (char**) calloc(1, res->names_size * sizeof (char*));
- if (res->names == NULL)
- goto err;
-
- for (i = 0; i < res->names_size; i++) {
- res->names[i] = calloc(PFI_UBI_VOL_NAME_LEN + 1, sizeof(char));
- if (res->names[i] == NULL)
- goto err;
- strncpy(res->names[i], tmp_names[i], PFI_UBI_VOL_NAME_LEN + 1);
- }
-
- goto out;
-
- err:
- if (res) {
- if (res->names) {
- for (i = 0; i < res->names_size; i++) {
- if (res->names[i]) {
- free(res->names[i]);
- }
- }
- free(res->names);
- }
- if (res->ids) {
- free(res->ids);
- }
- free(res);
- res = NULL;
- }
-
- out:
- bootenv_list_destroy(&ubi_id_list);
- bootenv_list_destroy(&ubi_name_list);
- if (tmp_names != NULL)
- free(tmp_names);
- *pfi_ubi = res;
- return rc;
-}
-
-
-int
-free_pdd_data(pdd_data_t* pdd_data)
-{
- if (*pdd_data) {
- free(*pdd_data);
- }
- *pdd_data = NULL;
-
- return 0;
-}
-
-int
-free_pfi_raw(pfi_raw_t* pfi_raw)
-{
- pfi_raw_t tmp = *pfi_raw;
- if (tmp) {
- if (tmp->starts)
- free(tmp->starts);
- free(tmp);
- }
- *pfi_raw = NULL;
-
- return 0;
-}
-
-int
-free_pfi_ubi(pfi_ubi_t* pfi_ubi)
-{
- size_t i;
- pfi_ubi_t tmp = *pfi_ubi;
- if (tmp) {
- if (tmp->ids)
- free(tmp->ids);
- if (tmp->names) {
- for (i = 0; i < tmp->names_size; i++) {
- if (tmp->names[i]) {
- free(tmp->names[i]);
- }
- }
- free(tmp->names);
- }
- free(tmp);
- }
- *pfi_ubi = NULL;
-
- return 0;
-}
-
-
-int
-read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi,
- char* err_buf, size_t err_buf_size)
-{
- int rc = 0;
- char mode[PFI_KEYWORD_LEN];
- char label[PFI_LABEL_LEN];
-
- *pfi_raws = mk_empty(); pfi_raw_t raw = NULL;
- *pfi_ubis = mk_empty(); pfi_ubi_t ubi = NULL;
- pfi_header pfi_header = NULL;
-
- /* read all headers from PFI and store them in lists */
- rc = pfi_header_init(&pfi_header);
- if (rc != 0) {
- EBUF("Cannot initialize pfi header.");
- goto err;
- }
- while ((rc == 0) && !feof(fp_pfi)) {
- rc = pfi_header_read(fp_pfi, pfi_header);
- if (rc != 0) {
- if (rc == PFI_DATA_START) {
- rc = 0;
- break; /* data section starts,
- all headers read */
- }
- else {
- goto err;
- }
- }
- rc = pfi_header_getstring(pfi_header, "label", label,
- PFI_LABEL_LEN);
- if (rc != 0) {
- EBUF("Cannot read 'label' from PFI.");
- goto err;
- }
- rc = pfi_header_getstring(pfi_header, "mode", mode,
- PFI_KEYWORD_LEN);
- if (rc != 0) {
- EBUF("Cannot read 'mode' from PFI.");
- goto err;
- }
- if (strcmp(mode, "ubi") == 0) {
- rc = read_pfi_ubi(pfi_header, fp_pfi, &ubi, label,
- err_buf, err_buf_size);
- if (rc != 0) {
- goto err;
- }
- *pfi_ubis = append_elem(ubi, *pfi_ubis);
- }
- else if (strcmp(mode, "raw") == 0) {
- rc = read_pfi_raw(pfi_header, fp_pfi, &raw, label,
- err_buf, err_buf_size);
- if (rc != 0) {
- goto err;
- }
- *pfi_raws = append_elem(raw, *pfi_raws);
- }
- else {
- EBUF("Recvieved unknown mode from PFI: %s", mode);
- goto err;
- }
- }
- goto out;
-
- err:
- *pfi_raws = remove_all((free_func_t)&free_pfi_raw, *pfi_raws);
- *pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, *pfi_ubis);
- out:
- pfi_header_destroy(&pfi_header);
- return rc;
-
-}
diff --git a/ubi-utils/src/reader.h b/ubi-utils/src/reader.h
deleted file mode 100644
index 715e464..0000000
--- a/ubi-utils/src/reader.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef __READER_H__
-#define __READER_H__
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Oliver Lohmann
- *
- * Read Platform Description Data (PDD).
- */
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include "pfi.h"
-#include "bootenv.h"
-#include "list.h"
-
-typedef enum flash_type_t {
- NAND_FLASH = 0,
- NOR_FLASH,
-} flash_type_t;
-
-typedef struct pdd_data *pdd_data_t;
-typedef struct pfi_raw *pfi_raw_t;
-typedef struct pfi_ubi *pfi_ubi_t;
-
-struct pdd_data {
- uint32_t flash_size;
- uint32_t flash_page_size;
- uint32_t eb_size;
- uint32_t vid_hdr_offset;
- flash_type_t flash_type;
-};
-
-struct pfi_raw {
- uint32_t data_size;
- uint32_t *starts;
- uint32_t starts_size;
- uint32_t crc;
-};
-
-struct pfi_ubi {
- uint32_t data_size;
- uint32_t alignment;
- uint32_t *ids;
- uint32_t ids_size;
- char **names;
- uint32_t names_size;
- uint32_t size;
- enum { pfi_ubi_dynamic, pfi_ubi_static } type;
- int curr_seqnum; /* specifies the seqnum taken in an update,
- default: 0 (used by pfiflash, ubimirror) */
- uint32_t crc;
-};
-
-int read_pdd_data(FILE* fp_pdd, pdd_data_t *pdd_data,
- char *err_buf, size_t err_buf_size);
-int read_pfi_raw(pfi_header pfi_hd, FILE* fp_pfi, pfi_raw_t *pfi_raw,
- const char *label, char *err_buf, size_t err_buf_size);
-int read_pfi_ubi(pfi_header pfi_hd, FILE* fp_pfi, pfi_ubi_t *pfi_ubi,
- const char *label, char *err_buf, size_t err_buf_size);
-
-/**
- * @brief Reads all pfi headers into list structures, separated by
- * RAW and UBI sections.
- */
-int read_pfi_headers(list_t *pfi_raws, list_t *pfi_ubis, FILE* fp_pfi,
- char* err_buf, size_t err_buf_size);
-int free_pdd_data(pdd_data_t *pdd_data);
-int free_pfi_raw(pfi_raw_t *raw_pfi);
-int free_pfi_ubi(pfi_ubi_t *pfi_ubi);
-
-#endif /* __READER_H__ */
diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/src/ubicrc32.c
index 0f10b31..8064439 100644
--- a/ubi-utils/src/ubicrc32.c
+++ b/ubi-utils/src/ubicrc32.c
@@ -91,8 +91,7 @@ static int parse_opt(int argc, char * const argv[])
int main(int argc, char * const argv[])
{
int err = 0;
- uint32_t crc32_table[256];
- uint32_t crc32 = UBI_CRC32_INIT;
+ uint32_t crc = UBI_CRC32_INIT;
char buf[BUFSIZE];
FILE *fp;
@@ -110,8 +109,6 @@ int main(int argc, char * const argv[])
if (err)
return err;
- init_crc32_table(crc32_table);
-
while (!feof(fp)) {
size_t read;
@@ -122,10 +119,10 @@ int main(int argc, char * const argv[])
err = -1;
goto out_close;
}
- crc32 = clc_crc32(crc32_table, crc32, buf, read);
+ crc = crc32(crc, buf, read);
}
- printf("0x%08x\n", crc32);
+ printf("0x%08x\n", crc);
out_close:
if (fp != stdin)
diff --git a/ubi-utils/src/ubigen.h b/ubi-utils/src/ubigen.h
deleted file mode 100644
index bf4b384..0000000
--- a/ubi-utils/src/ubigen.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Frank Haverkamp
- *
- * An utility to update UBI volumes.
- */
-
-#ifndef __UBIGEN_H__
-#define __UBIGEN_H__
-
-#include <stdio.h>
-#include <stdint.h>
-#include <mtd/ubi-header.h>
-#include <asm/byteorder.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define DEFAULT_BLOCKSIZE (128 * 1024)
-#define DEFAULT_PAGESIZE (2*1024)
-
-#define EUBIGEN_INVALID_TYPE 1
-#define EUBIGEN_INVALID_HDR_OFFSET 2
-#define EUBIGEN_INVALID_ALIGNMENT 3
-#define EUBIGEN_TOO_SMALL_EB 4
-#define EUBIGEN_MAX_ERROR 5
-
-typedef enum action {
- NO_ERROR = 0x00000000,
- BROKEN_HDR_CRC = 0x00000001,
- BROKEN_DATA_CRC = 0x00000002,
- BROKEN_DATA_SIZE = 0x00000004,
- BROKEN_OMIT_BLK = 0x00000008,
- MARK_AS_UPDATE = 0x00000010,
-} ubigen_action_t;
-
-typedef struct ubi_info *ubi_info_t;
-
-/**
- * @brief Initialize the internal CRC32 table.
- * @note Necessary because of the used crc32 function in UBI.
- * A usage of CRC32, from e.g. zlib will fail.
- */
-void ubigen_init(void);
-
-/**
- * @brief Create an ubigen handle.
- * @param ...
- * @return 0 On sucess.
- * else Error.
- * @note This parameterlist is ugly. But we have to use
- * two big structs and meta information internally,
- * filling them would be even uglier.
- */
-int ubigen_create(ubi_info_t *u, uint32_t vol_id, uint8_t vol_type,
- uint32_t eb_size, uint64_t ec, uint32_t alignment,
- uint8_t version, uint32_t vid_hdr_offset,
- uint8_t compat_flag, size_t data_size,
- FILE* fp_in, FILE* fp_out);
-
-/**
- * @brief Destroy an ubigen handle.
- * @param u Handle to free.
- * @return 0 On success.
- * else Error.
- */
-int ubigen_destroy(ubi_info_t *u);
-
-/**
- * @brief Get number of total logical EBs, necessary for the
- * complete storage of data in the handle.
- * @param u The handle.
- * @return 0 On success.
- * else Error.
- */
-int ubigen_get_leb_total(ubi_info_t u, size_t* total);
-
-/**
- * @brief Get the size in bytes of one logical EB in the handle.
- * @param u The handle.
- * @return 0 On success.
- * else Error.
- */
-int ubigen_get_leb_size(ubi_info_t u, size_t* size);
-
-
-/**
- * @brief Write a logical EB (fits exactly into 1 physical EB).
- * @param u Handle which holds all necessary data.
- * @param action Additional operations which shall be applied on this
- * logical eraseblock. Mostly injecting artifical errors.
- * @return 0 On success.
- * else Error.
- */
-int ubigen_write_leb(ubi_info_t u, ubigen_action_t action);
-
-/**
- * @brief Write a complete array of logical eraseblocks at once.
- * @param u Handle which holds all necessary data.
- * @return 0 On success.
- * else Error.
- */
-int ubigen_write_complete(ubi_info_t u);
-
-/**
- * @brief Write a single block which is extracted from the
- * binary input data.
- * @param u Handle which holds all necessary data.
- * @param blk Logical eraseblock which shall hold a inc. copy entry
- * and a bad data crc.
- * @return 0 On success.
- * else Error.
- */
-int ubigen_write_broken_update(ubi_info_t u, uint32_t blk);
-
-/**
- * @brief Use the current ubi_info data and some additional data
- * to set an UBI volume table entry from it.
- * @param u Handle which holds some of the necessary data.
- * @param res_bytes Number of reserved bytes which is stored in the volume
- * table entry.
- * @param name A string which shall be used as a volume label.
- * @param lvol_r A pointer to a volume table entry.
- * @return 0 On success.
- * else Error.
- */
-int ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes,
- const char* name, struct ubi_vtbl_record *lvol_rec);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__UBIGEN_H__ */
diff --git a/ubi-utils/src/unubi.c b/ubi-utils/src/unubi.c
index 5c1d324..1d4b35b 100644
--- a/ubi-utils/src/unubi.c
+++ b/ubi-utils/src/unubi.c
@@ -121,8 +121,6 @@ static const char *usage =
#define FN_VOLWH "%s/volume%03u" /* whole volume */
#define FN_VITBL "%s/vol_info_table%u" /* vol info table */
-static uint32_t crc32_table[256];
-
/* struct args:
* bsize int, blocksize of image blocks
* hsize int, eraseblock header size
@@ -351,7 +349,7 @@ data_crc(FILE* fpin, size_t length, uint32_t *ret_crc)
if (rc < 0)
return -1;
- crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, length);
+ crc = crc32(UBI_CRC32_INIT, buf, length);
*ret_crc = crc;
return 0;
}
@@ -462,8 +460,7 @@ extract_itable(FILE *fpin, struct eb_info *cur, size_t bsize, size_t num,
}
/* check crc */
- crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &rec,
- UBI_VTBL_RECORD_SIZE_CRC);
+ crc = crc32(UBI_CRC32_INIT, &rec, UBI_VTBL_RECORD_SIZE_CRC);
if (crc != __be32_to_cpu(rec.crc))
continue;
@@ -689,8 +686,7 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
}
/* check erasecounter header crc */
- crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->ec),
- UBI_EC_HDR_SIZE_CRC);
+ crc = crc32(UBI_CRC32_INIT, &(cur->ec), UBI_EC_HDR_SIZE_CRC);
if (__be32_to_cpu(cur->ec.hdr_crc) != crc) {
snprintf(reason, MAXPATH, ".invalid.ec_hdr_crc");
goto invalid;
@@ -734,8 +730,7 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
cur->ec_crc_ok = 1;
/* check volume id header crc */
- crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->vid),
- UBI_VID_HDR_SIZE_CRC);
+ crc = crc32(UBI_CRC32_INIT, &(cur->vid), UBI_VID_HDR_SIZE_CRC);
if (__be32_to_cpu(cur->vid.hdr_crc) != crc) {
snprintf(reason, MAXPATH, ".invalid.vid_hdr_crc");
goto invalid;
@@ -932,7 +927,6 @@ main(int argc, char *argv[])
vols_len = 0;
vols = NULL;
fpin = NULL;
- init_crc32_table(crc32_table);
/* setup struct args a */
memset(&a, 0, sizeof(a));
diff --git a/ubi-utils/src/unubi_analyze.c b/ubi-utils/src/unubi_analyze.c
index 2ab3b87..3f3a480 100644
--- a/ubi-utils/src/unubi_analyze.c
+++ b/ubi-utils/src/unubi_analyze.c
@@ -100,7 +100,7 @@ unubi_analyze_ec_hdr(struct eb_info *first, const char *path)
{
char filename[PATH_MAX + 1];
size_t count, eraseblocks;
- uint32_t crc, crc32_table[256];
+ uint32_t crc;
uint64_t *erase_counts;
FILE* fpdata;
FILE* fpplot;
@@ -109,9 +109,6 @@ unubi_analyze_ec_hdr(struct eb_info *first, const char *path)
if (first == NULL)
return -1;
- /* crc check still needed for `first' linked list */
- init_crc32_table(crc32_table);
-
/* prepare output files */
memset(filename, 0, PATH_MAX + 1);
snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_DATA);
@@ -164,8 +161,7 @@ unubi_analyze_ec_hdr(struct eb_info *first, const char *path)
fprintf(fpdata, "# eraseblock_no actual_erase_count "
"sorted_erase_count\n");
while (cur != NULL) {
- crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &cur->ec,
- UBI_EC_HDR_SIZE_CRC);
+ crc = crc32(UBI_CRC32_INIT, &cur->ec, UBI_EC_HDR_SIZE_CRC);
if ((__be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) ||
(crc != __be32_to_cpu(cur->ec.hdr_crc)))