diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-01-23 19:34:52 +0200 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-01-23 19:34:52 +0200 |
commit | 3ad29ab55ad71d706152781b70a43d9f6be407b9 (patch) | |
tree | 4e5a41b23e771faef0f633c6570210a42bd9c037 | |
parent | 22f5fe49d60ea43524a902408b3112a78f2c5aae (diff) |
ubi-utils: remove all old tools
Remove all old tools because I cannot maintain them and the original
authors do not seem to have time for this. Some of the tools do not
work properly, some are just vague and undocumented and seem to be
oriented to the environment of the IBM guys. Nevertheless, I'll
return the tool as is in the next commit, becouse they are still
useful.
This commit also adds a ubinize utility to generate UBI images.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
81 files changed, 2312 insertions, 17713 deletions
diff --git a/ubi-utils/LICENSE.libiniparser b/ubi-utils/LICENSE.libiniparser new file mode 100644 index 0000000..dbfa45d --- /dev/null +++ b/ubi-utils/LICENSE.libiniparser @@ -0,0 +1,21 @@ +Copyright (c) 2000-2007 by Nicolas Devillard. +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile index 1f8e543..8d4412d 100644 --- a/ubi-utils/Makefile +++ b/ubi-utils/Makefile @@ -10,65 +10,53 @@ MANDIR=/usr/man INCLUDEDIR=/usr/include CC := $(CROSS)gcc -CFLAGS := -I./inc -I./src -I$(KERNELHDR) $(OPTFLAGS) -Werror -Wall -O0 -g +CFLAGS := -Iinclude -Isrc -I$(KERNELHDR) $(OPTFLAGS) -Werror -Wall -PERLPROGS = mkpfi -TARGETS = ubiupdate ubimkvol ubirmvol ubicrc32 ubinfo ubiattach ubidetach \ - unubi pfi2bin +LIBS = libubi libubigen libiniparser +UTILS = ubiupdate ubimkvol ubirmvol ubicrc32 ubinfo ubiattach ubidetach ubinize -vpath %.c ./src +vpath %.c src -%: %.o - $(CC) $(LDFLAGS) -g -o $@ $^ +all: $(UTILS) -%.o: %.c - $(CC) $(CFLAGS) -g -c -o $@ $< -g -Wp,-MD,.$(shell basename $<).dep - -all: $(TARGETS) libubi.a - -IGNORE=${wildcard .*.c.dep} --include ${IGNORE} - -clean: - rm -rf *.o $(TARGETS) .*.c.dep libubi.a - -libubi.a: libubi.o - ar cr $@ $^ +# The below cancels existing implicite rule to make programs from .c files, +# in order to force make using our rule defined below +%: %.c -ubidetach: ubidetach.o common.o libubi.o - $(CC) $(LDFLAGS) -o $@ $^ +# The below is the rule to get an .o file from a .c file +%.o: %.c + $(CC) $(CFLAGS) $< -c -o $@ -ubiattach: ubiattach.o common.o libubi.o - $(CC) $(LDFLAGS) -o $@ $^ +# And the below is the rule to get final executable from its .o and common.o +%: libubi %.o common.o + $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@ -ubinfo: ubinfo.o common.o libubi.o - $(CC) $(LDFLAGS) -o $@ $^ +ubicrc32: ubicrc32.o crc32.o + $(CC) $(CFLAGS) -o $@ $^ -ubiupdate: ubiupdate.o common.o libubi.o - $(CC) $(LDFLAGS) -o $@ $^ +ubinize: ubinize.o common.o crc32.o libiniparser libubigen + $(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@ -ubimkvol: ubimkvol.o common.o libubi.o - $(CC) $(LDFLAGS) -o $@ $^ +libubi: libubi.o + $(AR) crv $@.a $^ + ranlib $@.a -ubirmvol: ubirmvol.o common.o libubi.o - $(CC) $(LDFLAGS) -o $@ $^ +libubigen: libubigen.o + $(AR) crv $@.a $^ + ranlib $@.a -ubicrc32: ubicrc32.o crc32.o - $(CC) $(LDFLAGS) -o $@ $^ +libiniparser: libiniparser.o dictionary.o + $(AR) crv $@.a $^ + ranlib $@.a -unubi: unubi.o crc32.o unubi_analyze.o eb_chain.o - $(CC) $(LDFLAGS) -o $@ $^ - -pfi2bin: pfi2bin.o common.o list.o crc32.o libubigen.o bootenv.o \ - hashmap.o libpfi.o common.o - $(CC) $(LDFLAGS) -o $@ $^ +clean: + rm -rf *.o $(addsuffix .a, $(LIBS)) $(UTILS) .*.c.dep -install: ${TARGETS} +install: ${UTILS} mkdir -p ${DESTDIR}/${SBINDIR} - install -m0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/ - (cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/) + install -m0755 ${UTILS} ${DESTDIR}/${SBINDIR}/ uninstall: - for file in ${TARGETS} ${PERLPROGS}; do \ + for file in ${UTILS}; do \ $(RM) ${DESTDIR}/${SBINDIR}/$$file; \ done diff --git a/ubi-utils/inc/libpfi.h b/ubi-utils/inc/libpfi.h deleted file mode 100644 index 6aca4be..0000000 --- a/ubi-utils/inc/libpfi.h +++ /dev/null @@ -1,257 +0,0 @@ -#ifndef __pfi_h -#define __pfi_h -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * @file pfi.h - * - * @author Oliver Lohmann <oliloh@de.ibm.com> - * Andreas Arnez <arnez@de.ibm.com> - * Joern Engel <engeljoe@de.ibm.com> - * Frank Haverkamp <haverkam@de.ibm.com> - * - * @brief libpfi will hold all code to create and process pfi - * images. Definitions made in this file are equaly usable for the - * development host and the target system. - * - * @note This header additionally holds the official definitions for - * the pfi headers. - */ - -#include <stdio.h> /* FILE */ -#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 */ - -#define PFI_ENOVERSION 1 /* unknown version */ -#define PFI_ENOHEADER 2 /* not a pfi header */ -#define PFI_EINSUFF 3 /* insufficient information */ -#define PFI_EUNDEF 4 /* key not defined */ -#define PFI_ENOMEM 5 /* out of memory */ -#define PFI_EBADTYPE 6 /* bad data type */ -#define PFI_EFILE 7 /* file I/O error: see errno */ -#define PFI_EFILEINVAL 8 /* file format not valid */ -#define PFI_EINVAL 9 /* invalid parameter */ -#define PFI_ERANGE 10 /* invalid range */ -#define PFI_EMODE 11 /* expecting other mode in this header */ -#define PFI_DATA_START 12 /* data section starts */ -#define PFI_EMAX 13 /* should be always larger as the largest - error code */ - -#define PFI_LABEL_LEN 64 /* This is the maximum length for a - PFI header label */ -#define PFI_KEYWORD_LEN 32 /* This is the maximum length for an - entry in the mode and type fields */ - -#define PFI_UBI_MAX_VOLUMES 128 -#define PFI_UBI_VOL_NAME_LEN 127 - -/** - * @brief The pfi header allows to set flags which influence the flashing - * behaviour. - */ -#define PFI_FLAG_PROTECTED 0x00000001 - -struct pfi_header; - -/** - * @brief Initialize a pfi header object. - * - * @param head Pointer to handle. This function allocates memory - * for this data structure. - * @return 0 on success, otherwise: - * PFI_ENOMEM : no memory available for the handle. - */ -int pfi_header_init (struct pfi_header **head); - - -/** - * @brief Destroy a pfi header object. - * - * @param head handle. head is invalid after calling this function. - * @return 0 always. - */ -int pfi_header_destroy (struct pfi_header **head); - - -/** - * @brief Add a key/value pair to a pfi header object. - * - * @param head handle. - * @param key pointer to key string. Must be 0 terminated. - * @param value pointer to value string. Must be 0 terminated. - * @return 0 on success, otherwise: - * PFI_EUNDEF : key was not found. - * PFI_ENOMEM : no memory available for the handle. - * PFI_EBADTYPE : value is not an hex string. This happens - * when the key stores an integer and the - * new value is not convertable e.g. not in - * 0xXXXXXXXX format. - */ -int pfi_header_setvalue (struct pfi_header *head, - const char *key, const char *value); - - -/** - * @brief Add a key/value pair to a pfi header object. Provide the - * value as a number. - * - * @param head handle. - * @param key pointer to key string. Must be 0 terminated. - * @param value value to set. - * @return 0 on success, otherwise: - * PFI_EUNDEF : key was not found. - * PFI_EBADTYPE : value is not a string. This happens - * when the key stores a string. - */ -int pfi_header_setnumber (struct pfi_header *head, - const char *key, uint32_t value); - - -/** - * @brief For a given key, return the numerical value stored in a - * pfi header object. - * - * @param head handle. - * @param key pointer to key string. Must be 0 terminated. - * @param value pointer to value. - * @return 0 on success, otherwise: - * PFI_EUNDEF : key was not found. - * PFI_EBADTYPE : stored value is not an integer but a string. - */ -int pfi_header_getnumber (struct pfi_header *head, - const char *key, uint32_t *value); - - -static inline uint32_t -pfi_getnumber(struct pfi_header *head, const char *key) -{ - uint32_t value; - pfi_header_getnumber(head, key, &value); - return value; -} - -/** - * @brief For a given key, return the string value stored in a pfi - * header object. - * - * @param head handle. - * @param key pointer to key string. Must be 0 terminated. - * @param value pointer to value string. Memory must be allocated by the user. - * @return 0 on success, otherwise: - * PFI_EUNDEF : key was not found. - * PFI_EBADTYPE : stored value is not a string but an integer. - */ -int pfi_header_getstring (struct pfi_header *head, - const char *key, char *value, size_t size); - - -/** - * @brief Write a pfi header object into a given file. - * - * @param out output stream. - * @param head handle. - * @return 0 on success, error values otherwise: - * PFI_EINSUFF : not all mandatory fields are filled. - * PFI_ENOHEADER : wrong header version or magic number. - * -E* : see <asm/errno.h>. - */ -int pfi_header_write (FILE *out, struct pfi_header *head); - - -/** - * @brief Read a pfi header object from a given file. - * - * @param in input stream. - * @param head handle. - * @return 0 on success, error values otherwise: - * PFI_ENOVERSION: unknown header version. - * PFI_EFILE : cannot read enough data. - * PFI_ENOHEADER : wrong header version or magic number. - * -E* : see <asm/errno.h>. - * - * If the header verification returned success the user can assume that - * all mandatory fields for a particular version are accessible. Checking - * the return code when calling the get-function for those keys is not - * required in those cases. For optional fields the checking must still be - * done. - */ -int pfi_header_read (FILE *in, struct pfi_header *head); - - -/** - * @brief Display a pfi header in human-readable form. - * - * @param out output stream. - * @param head handle. - * @return always 0. - * - * @note Prints out that it is not implemented and whom you should - * contact if you need it urgently!. - */ -int pfi_header_dump (FILE *out, struct pfi_header *head); - - -/* - * @brief Iterates over a stream of pfi files. The iterator function - * must advance the file pointer in FILE *in to the next pfi - * header. Function exists on feof(in). - * - * @param in input file descriptor, must be open and valid. - * @param func iterator function called when pfi header could be - * read and was validated. The function must return 0 on - * success. - * @return See pfi_header_init and pfi_header_read. - * PFI_EINVAL : func is not valid - * 0 ok. - */ -typedef int (* pfi_read_func)(FILE *in, struct pfi_header *hdr, void *priv_data); - -int pfi_read (FILE *in, pfi_read_func func, void *priv_data); - - -#ifdef __cplusplus -} -#endif - -#endif /* __pfi_h */ diff --git a/ubi-utils/include/libiniparser.h b/ubi-utils/include/libiniparser.h new file mode 100644 index 0000000..be3c667 --- /dev/null +++ b/ubi-utils/include/libiniparser.h @@ -0,0 +1,280 @@ + +/*-------------------------------------------------------------------------*/ +/** + @file iniparser.h + @author N. Devillard + @date Sep 2007 + @version 3.0 + @brief Parser for ini files. +*/ +/*--------------------------------------------------------------------------*/ + +/* + $Id: iniparser.h,v 1.24 2007-11-23 21:38:19 ndevilla Exp $ + $Revision: 1.24 $ +*/ + +#ifndef _INIPARSER_H_ +#define _INIPARSER_H_ + +/*--------------------------------------------------------------------------- + Includes + ---------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * The following #include is necessary on many Unixes but not Linux. + * It is not needed for Windows platforms. + * Uncomment it if needed. + */ +/* #include <unistd.h> */ + +#include "dictionary.h" + +/*--------------------------------------------------------------------------- + Macros + ---------------------------------------------------------------------------*/ +/** For backwards compatibility only */ +#define iniparser_getstr(d, k) iniparser_getstring(d, k, NULL) +#define iniparser_setstr iniparser_setstring + +/*-------------------------------------------------------------------------*/ +/** + @brief Get number of sections in a dictionary + @param d Dictionary to examine + @return int Number of sections found in dictionary + + This function returns the number of sections found in a dictionary. + The test to recognize sections is done on the string stored in the + dictionary: a section name is given as "section" whereas a key is + stored as "section:key", thus the test looks for entries that do not + contain a colon. + + This clearly fails in the case a section name contains a colon, but + this should simply be avoided. + + This function returns -1 in case of error. + */ +/*--------------------------------------------------------------------------*/ + +int iniparser_getnsec(dictionary * d); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Get name for section n in a dictionary. + @param d Dictionary to examine + @param n Section number (from 0 to nsec-1). + @return Pointer to char string + + This function locates the n-th section in a dictionary and returns + its name as a pointer to a string statically allocated inside the + dictionary. Do not free or modify the returned string! + + This function returns NULL in case of error. + */ +/*--------------------------------------------------------------------------*/ + +char * iniparser_getsecname(dictionary * d, int n); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Save a dictionary to a loadable ini file + @param d Dictionary to dump + @param f Opened file pointer to dump to + @return void + + This function dumps a given dictionary into a loadable ini file. + It is Ok to specify @c stderr or @c stdout as output files. + */ +/*--------------------------------------------------------------------------*/ + +void iniparser_dump_ini(dictionary * d, FILE * f); + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump. + @param f Opened file pointer to dump to. + @return void + + This function prints out the contents of a dictionary, one element by + line, onto the provided file pointer. It is OK to specify @c stderr + or @c stdout as output files. This function is meant for debugging + purposes mostly. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_dump(dictionary * d, FILE * f); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key + @param d Dictionary to search + @param key Key string to look for + @param def Default value to return if key not found. + @return pointer to statically allocated character string + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the pointer passed as 'def' is returned. + The returned char pointer is pointing to a string allocated in + the dictionary, do not free or modify it. + */ +/*--------------------------------------------------------------------------*/ +char * iniparser_getstring(dictionary * d, const char * key, char * def); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to an int + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + Supported values for integers include the usual C notation + so decimal, octal (starting with 0) and hexadecimal (starting with 0x) + are supported. Examples: + + - "42" -> 42 + - "042" -> 34 (octal -> decimal) + - "0x42" -> 66 (hexa -> decimal) + + Warning: the conversion may overflow in various ways. Conversion is + totally outsourced to strtol(), see the associated man page for overflow + handling. + + Credits: Thanks to A. Becker for suggesting strtol() + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getint(dictionary * d, const char * key, int notfound); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a double + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return double + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + */ +/*--------------------------------------------------------------------------*/ +double iniparser_getdouble(dictionary * d, char * key, double notfound); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a boolean + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + A true boolean is found if one of the following is matched: + + - A string starting with 'y' + - A string starting with 'Y' + - A string starting with 't' + - A string starting with 'T' + - A string starting with '1' + + A false boolean is found if one of the following is matched: + + - A string starting with 'n' + - A string starting with 'N' + - A string starting with 'f' + - A string starting with 'F' + - A string starting with '0' + + The notfound value returned if no boolean is identified, does not + necessarily have to be 0 or 1. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getboolean(dictionary * d, const char * key, int notfound); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Set an entry in a dictionary. + @param ini Dictionary to modify. + @param entry Entry to modify (entry name) + @param val New value to associate to the entry. + @return int 0 if Ok, -1 otherwise. + + If the given entry can be found in the dictionary, it is modified to + contain the provided value. If it cannot be found, -1 is returned. + It is Ok to set val to NULL. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_setstring(dictionary * ini, char * entry, char * val); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete an entry in a dictionary + @param ini Dictionary to modify + @param entry Entry to delete (entry name) + @return void + + If the given entry can be found, it is deleted from the dictionary. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_unset(dictionary * ini, char * entry); + +/*-------------------------------------------------------------------------*/ +/** + @brief Finds out if a given entry exists in a dictionary + @param ini Dictionary to search + @param entry Name of the entry to look for + @return integer 1 if entry exists, 0 otherwise + + Finds out if a given entry exists in the dictionary. Since sections + are stored as keys with NULL associated values, this is the only way + of querying for the presence of sections in a dictionary. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_find_entry(dictionary * ini, char * entry) ; + +/*-------------------------------------------------------------------------*/ +/** + @brief Parse an ini file and return an allocated dictionary object + @param ininame Name of the ini file to read. + @return Pointer to newly allocated dictionary + + This is the parser for ini files. This function is called, providing + the name of the file to be read. It returns a dictionary object that + should not be accessed directly, but through accessor functions + instead. + + The returned dictionary must be freed using iniparser_freedict(). + */ +/*--------------------------------------------------------------------------*/ +dictionary * iniparser_load(const char * ininame); + +/*-------------------------------------------------------------------------*/ +/** + @brief Free all memory associated to an ini dictionary + @param d Dictionary to free + @return void + + Free all memory associated to an ini dictionary. + It is mandatory to call this function before the dictionary object + gets out of the current context. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_freedict(dictionary * d); + +#endif diff --git a/ubi-utils/inc/libubi.h b/ubi-utils/include/libubi.h index 0cdb67c..0cdb67c 100644 --- a/ubi-utils/inc/libubi.h +++ b/ubi-utils/include/libubi.h diff --git a/ubi-utils/inc/libubigen.h b/ubi-utils/include/libubigen.h index 5315a72..66f5fb1 100644 --- a/ubi-utils/inc/libubigen.h +++ b/ubi-utils/include/libubigen.h @@ -41,6 +41,8 @@ extern "C" { * @data_offs: data offset * @ubi_ver: UBI version * @ec: initial erase counter + * @vtbl_size: volume table size + * @max_volumes: maximum amount of volumes */ struct ubigen_info { @@ -51,6 +53,8 @@ struct ubigen_info int data_offs; int ubi_ver; long long ec; + int vtbl_size; + int max_volumes; }; /** @@ -87,10 +91,11 @@ struct ubigen_vol_info 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); +struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui); +int ubigen_get_vtbl_size(const struct ubigen_info *ui); +int ubigen_add_volume(const struct ubigen_info *ui, + const struct ubigen_vol_info *vi, + struct ubi_vtbl_record *vtbl); int ubigen_write_volume(const struct ubigen_info *ui, const struct ubigen_vol_info *vi, long long bytes, FILE *in, FILE *out); diff --git a/ubi-utils/scripts/mkdevs.pl b/ubi-utils/scripts/mkdevs.pl deleted file mode 100755 index 46d47c5..0000000 --- a/ubi-utils/scripts/mkdevs.pl +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/perl -w - -# -# Author: Artem B. Bityutskiy <dedekind@oktetlabs.ru> -# -# A small scrip which creates UBI device nodes in /dev. UBI allocates -# major number dynamically, so the script looks at /proc/devices to find -# out UBI's major number. -# - -# Create the control device as well if this UBI version supports them (were -# added sice Linux kernel 2.6.24) -my $ctrl = "/sys/class/misc/ubi_ctrl/dev"; - -if (-e "$ctrl") { - open FILE, "<", $ctrl or die "Cannot open $ctrl file: $!\n"; - my $devnums = <FILE>; - close FILE; - - $devnums =~ m/(\d+):(\d+)/; - system("mknod /dev/ubi_ctrl c $1 $2"); -} - -my $proc = '/proc/devices'; -my $regexp = '(\d+) (ubi\d+)$'; - -open FILE, "<", $proc or die "Cannot open $proc file: $!\n"; -my @file = <FILE>; -close FILE; - -foreach (@file) { - next if not m/$regexp/g; - print "found $2\n"; - - system("rm -rf /dev/$2"); - system("mknod /dev/$2 c $1 0"); - - for (my $i = 0; $i < 128; $i += 1) { - system("rm -rf /dev/$2_$i"); - my $j = $i + 1; - system("mknod /dev/$2_$i c $1 $j"); - } -} - diff --git a/ubi-utils/scripts/mkpfi b/ubi-utils/scripts/mkpfi deleted file mode 100755 index 5cc69d9..0000000 --- a/ubi-utils/scripts/mkpfi +++ /dev/null @@ -1,708 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (c) International Business Machines Corp., 2006 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -# the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# - -# -# mkpfi -# -# This perl program is assembles PFI files from a config file. -# -# Author: Oliver Lohmann (oliloh@de.ibm.com) -# -use warnings; -use strict; -use lib "/usr/lib/perl5"; # Please change this path as you need it, or - # make a proposal how this could be done - # nicer. -use Getopt::Long; -use Pod::Usage; -use Config::IniFiles; -use File::Temp; - -# ---------------------------------------------------------------------------- -# Versions -our $version : unique = "0.1"; -our $pfi_version : unique = "0x1"; - -# ---------------------------------------------------------------------------- -# Globals -my $verbose = 0; -my $cfg; - -my $err_prefix = "mkpfi error"; - -my %opts = (); -my %files = (config => ""); -my @tmp_files; - -my %tools = (ubicrc32 => "ubicrc32"); - -# ---------------------------------------------------------------------------- -# Processing the input sections -# -# The idea is to combine each section entry with a function -# in order to allow some kind of preprocessing for the values -# before they are written into the PFI file. -# This is especially useful to be more verbose and -# user-friendly in the layout file. -# -# All key-function hashes are applied after the general -# validation of the configuration file. -# If any mandatory key is missing in a section the user -# will be informed and the PFI creation process is aborted. -# -# Default keys will be checked for their presence inside the config -# file. If they are missing, they will be generated with appr. values. - -# Mandatory keys for UBI volumes. -my %ubi_keys = ("ubi_ids" => \&check_id_list, - "ubi_size" => \&replace_num, - "ubi_type" => \&replace_type, - "ubi_names" => \&remove_spaces, - "ubi_alignment" => \&replace_num); - -# Mandatory keys for RAW sections. -my %raw_keys = ("raw_starts" => \&expand_starts, - "raw_total_size" => \&replace_num); - -# Common default keys for documentation and control purposes. -my %common_keys = ("flags" => \&replace_num, - "label" => \&do_nothing); - -# Define any defaults here. Values which maintained in this default -# region need not to be specified by the user explicitly. -my %def_ubi_keys = ("ubi_alignment" => [\&set_default, "0x1"]); -my %def_raw_keys = (); -my %def_common_keys = ("flags" => [\&set_default, "0x0"], - "label" => [\&generate_label, ""]); - -# ---------------------------------------------------------------------------- -# Input keys, actually the path to the input data. - -my %input_keys = ("image" => \&do_nothing); - -# Placeholder keys allow the replacement via a special -# purpose function. E.g. the bootenv_file key will be used -# to generate bootenv binary data from an text file and -# replace the bootenv_file key with an image key to handle it -# in the same way in the further creation process. -my %input_placeholder_keys = ("bootenv_file" => \&create_bootenv_image); - -# ---------------------------------------------------------------------------- -# Helper - -# @brief Get current time string. -sub get_date { - my $tmp = scalar localtime; - $tmp =~ s/ /_/g; - return $tmp; -} - -# @brief Print an info message to stdout. -sub infomsg($) { - my $str = shift; - - print "mkpfi: $str\n" if $verbose; -} - -# @brief Print an error message to stderr. -sub errmsg($) { - my $str = shift; - print STDERR "$err_prefix: $str\n"; -} - -# @brief Print a warning message to stderr. -sub warnmsg($) { - my $str = shift; - print STDERR "mkpfi warning: $str\n"; -} - -sub parse_command_line($) { - my $opt = shift; - my $result = GetOptions( "help" => \$$opt{'help'}, - "man" => \$$opt{'man'}, - "verbose" => \$$opt{'verbose'}, - "config=s" => \$$opt{'config'}, - ) or pod2usage(2); - pod2usage(1) if defined ($$opt{help}); - pod2usage(-verbose => 2) if defined ($$opt{man}); - - $verbose = $$opt{verbose} if defined $$opt{verbose}; - - if (!defined $$opt{config}) { - errmsg("no config file specified (use --help)"); - exit 1; - } -} - -# @brief Check if all needed tools are in PATH. -sub check_tools { - my $err = 0; - my $key; - - foreach $key (keys %tools) { - if (`which $tools{$key}` eq "") { - errmsg("\"$tools{$key}\" not found, add it to your path"); - $err = 1; - } - } - die "$err_prefix: cannot not find all needed tools\n" if $err; -} - -sub open_cfg_file($) { - my $fname = shift; - my $res = new Config::IniFiles(-file => $fname); - - die "$err_prefix: cannot load config file \"$fname\"\n" if (!defined $res); - return $res; -} - -sub set_default($$$$) { - my ($cfg, $section, $parameter, $def_value) = @_; - $cfg->newval($section, $parameter, $def_value); - return; -} - -sub generate_label($$$$) { - my ($cfg, $section, $parameter, $def_value) = @_; - my $new_label = $def_value . $section; - $new_label .= "_" . get_date; - $cfg->newval($section, $parameter, $new_label); - return; -} - -# @brief Converts any num to a unified hex string, i.e the resulting value -# always starts with "0x" and is aligned to 8 hexdigits. -# @return Returns 0 on success, otherwise an error occured. -# -sub any_num_to_hex($$) { - my $val = shift; - my $res = shift; - - # M(iB) - if ($val =~ m/([0-9]+)[Mm][i]?[Bb]?/g) { - $$res = sprintf("0x%08x", $1 * 1024 * 1024); - } - # k(iB) - elsif ($val =~ m/([0-9]+)[kK][i]?[Bb]?/g) { - $$res = sprintf("0x%08x", $1 * 1024); - } - # hex - elsif ($val =~ m/0x?([0-9a-fA-F]+)/g) { - $$res = sprintf("0x%08x", hex $1); - } - # decimal - elsif ($val =~ m/^([0-9]+)$/g) { - $$res = sprintf("0x%08x", $1); - } - else { - $$res = ""; - return -1; - } - - return 0; -} - -sub remove_spaces($$$) { - my ($cfg, $section, $parameter) = @_; - my ($start, @starts, @new_starts); - my $val = $cfg->val($section, $parameter); - my $res; - - $val =~ s/ //g; # spaces - $cfg->newval($section, $parameter, $val); -} - -sub expand_starts($$$) { - my ($cfg, $section, $parameter) = @_; - my ($start, @starts, @new_starts); - my $val = $cfg->val($section, $parameter); - my $res; - - $val =~ s/ //g; # spaces - @starts = split(/,/, $val); - - foreach $start (@starts) { - if (any_num_to_hex($start, \$res) != 0) { - errmsg("section [$section]: expecting a list of numeric " . - "values for parameter \"$parameter\""); - exit 1; - } - push (@new_starts, $res); - } - $res = join(',', @starts); - - $cfg->newval($section, $parameter, $res); -} - -sub check_id_list($$$) { - my ($cfg, $section, $parameter) = @_; - my $val = $cfg->val($section, $parameter); - my $res; - - if (!($val =~ m/^[0-9]+[,0-9]*/)) { - errmsg("syntax error in 'ubi_ids' in " . - "section \"$section\": $val"); - exit 1; - } -} - -sub replace_type($$$) { - my ($cfg, $section, $parameter) = @_; - my $val = $cfg->val($section, $parameter); - my $res; - - $res = lc($val); - grep {$res eq $_} ('static', 'dynamic') - or die "$err_prefix: unknown UBI Volume type in section" . - "[$section]: $val\n"; - - $cfg->newval($section, $parameter, $res); -} - - -sub replace_num($$$) { - my ($cfg, $section, $parameter) = @_; - my $val = $cfg->val($section, $parameter); - my $res = ""; - - if (any_num_to_hex($val, \$res) != 0) { - errmsg("section [$section]: expecting a numeric value " . - "for parameter: $parameter"); - exit 1; - } - $cfg->newval($section, $parameter, $res); -} - -sub do_nothing($$$) { - my ($cfg, $section, $parameter) = @_; - return; -} - -sub bootenv_sanity_check($) { - my $env = shift; # hash array containing bootenv - my %pdd = (); - - defined($$env{'pdd'}) or return "'pdd' not defined"; - foreach (split /,/, $$env{'pdd'}) { - defined($$env{$_}) or return "undefined '$_' in pdd"; - $pdd{$_} = 1; - } - - defined $$env{'pdd_preserve'} or - return ""; - foreach (split /,/, $$env{'pdd_preserve'}) { - defined($pdd{$_}) - or return "pdd_preserve field '$_' not in pdd"; - } - return ""; -} - -sub create_bootenv_image($$$) { - my ($cfg, $section, $parameter) = @_; - my $txt_fn = $cfg->val($section, "bootenv_file"); - my $in; - - my %value = (); - my @key = (); - - open $in, "<", $txt_fn - or die "$err_prefix: can't open bootenv file '$txt_fn'.\n"; - while (<$in>) { - next if (/^\s*(\#.*)?$/); # Skip comments/whitespace. - - if (/^(\S+?)\+\=(.*)$/) { - defined($value{$1}) or - die "$err_prefix: $txt_fn:$.: appending to" . - " non-existent '$1'\n"; - $value{$1} .= $2; - } elsif (/^(\S+?)\=(.*)$/) { - not defined($value{$1}) or - die "$err_prefix: $txt_fn:$.: trying to" . - " redefine '$1'\n"; - push @key, $1; - $value{$1} = $2; - } else { - die "$err_prefix: $txt_fn:$.: unrecognized syntax\n"; - } - } - close $in; - - $_ = &bootenv_sanity_check(\%value) - and die "$err_prefix: $txt_fn: $_\n"; - - my $tmp_file = new File::Temp(); - push (@tmp_files, $tmp_file); - - foreach (@key) { - print $tmp_file "$_=", $value{$_}, "\0"; - } - close $tmp_file; - - $cfg->newval($section, "image", $tmp_file-> filename); -} - -sub process_keys($$$) { - my ($cfg, $section, $keys) = @_; - my @parameters = $cfg->Parameters($section); - my $i; - - for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) { - if (defined($$keys{$parameters[$i]})) { - $$keys{$parameters[$i]}->($cfg, $section, - $parameters[$i]); - } - } - -} - -sub is_in_keylist($$) { - my ($key, $keys) = @_; - my $i; - - for ($i = 0; $i < scalar(@$keys); $i++) { - if ($$keys[$i] eq $key) { - return 1; - } - } - - return 0; -} - -sub check_default_keys($$$) { - my ($cfg, $section, $keys) = @_; - my @parameters = $cfg->Parameters($section); - my $key; - - foreach $key (keys %$keys) { - if (!is_in_keylist($key, \@parameters)) { - $$keys{$key}[0]-> - ($cfg, $section, $key, $$keys{$key}[1]); - } - } - -} - - - -sub check_keys($$$) { - my ($cfg, $section, $keys) = @_; - my @parameters = $cfg->Parameters($section); - my ($i, $key, $err); - - $err = 0; - for ($i = 0 ; $i < scalar(@$keys) ; $i++ ) { - if (!is_in_keylist($$keys[$i], \@parameters)) { - errmsg("section [$section]: missing key \"$$keys[$i]\""); - $err = 1; - } - } - - exit 1 if $err; -} - -sub push_pfi_data($$$$$) { - my ($cfg, $section, $pfi_infos, $keys, $mode) = @_; - my ($tmp, $i, $hdr); - - my %pfi_info = (); - $pfi_info{'mode'} = $mode; - $pfi_info{'image'} = $cfg->val($section, "image"); - - # Build the PFI header - $hdr = sprintf("PFI!\n"); - $hdr .= sprintf("version=0x%08x\n", hex $pfi_version); - $hdr .= sprintf("mode=$mode\n"); - - # Calculate the size of the binary data part - $tmp = -s $cfg->val($section, "image"); - if (!defined $tmp) { - errmsg("section [$section]: missing input image \"" . - $cfg->val($section, "image") . "\""); - exit 1; - } - - # Check for the image to fit into the given space - my $quota; - if ($mode eq 'raw') { - $quota = oct $cfg->val($section, "raw_total_size"); - } elsif ($mode eq 'ubi') { - $quota = oct $cfg->val($section, "ubi_size"); - } - $tmp <= $quota - or die "$err_prefix: image file too big: " . - $cfg->val($section, "image") . "\n"; - $pfi_info{'size'} = $tmp; - - $hdr .= sprintf("size=0x%08x\n", $tmp); - - my $img_file = $cfg->val($section, "image"); - my $crc32 = `$tools{'ubicrc32'} $img_file 2>&1`; - if (any_num_to_hex($crc32, \$tmp) != 0) { - die "$err_prefix: $tools{'ubicrc32'} returned an error\n"; - } - $hdr .= sprintf("crc=$tmp\n"); - - # Process all remaining keys - for ($i = 0; $i < scalar (@$keys); $i++) { - if ($$keys[$i] eq "image") { # special case image input file - if (! -e ($tmp = $cfg->val($section, "image"))) { - errmsg("section [$section]: cannot find " . - "input file $tmp"); - exit 1; - } - next; - } - $hdr .= sprintf("%s=%s\n", $$keys[$i], - $cfg->val($section, $$keys[$i])); - } - - $hdr .= sprintf("\n"); # end marker for PFI-header - - $pfi_info{'header'} = $hdr; - - # store in the header list - push @$pfi_infos, \%pfi_info; -} - -sub process_section($$$$$$) { - my ($cfg, $section, $pfi_infos, $custom_keys, - $def_custom_keys, $mode) = @_; - my @keys = (keys %common_keys, keys %$custom_keys); - my @complete_keys = (@keys, keys %input_keys); - - # set defaults if necessary - check_default_keys($cfg, $section, $def_custom_keys); - check_default_keys($cfg, $section, \%def_common_keys); - - # check for placeholders... - process_keys($cfg, $section, \%input_placeholder_keys); - - # VALIDATE layout.cfg entries - check_keys($cfg, $section, \@complete_keys); - - # execute linked functions (if any) - process_keys($cfg, $section, \%common_keys); - process_keys($cfg, $section, $custom_keys); - - push_pfi_data($cfg, $section, $pfi_infos, \@keys, $mode); -} - -sub get_section_info($$) { - my ($cfg, $section) = @_; - my @parameters = $cfg->Parameters($section); - my ($ubi, $raw, $i, @res); - - $ubi = $raw = 0; - for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) { - if ($parameters[$i] =~ m/ubi_/gi) { - $ubi = 1; - @res = (\%ubi_keys, \%def_ubi_keys, "ubi"); - } - if ($parameters[$i] =~ m/raw_/gi) { - $raw = 1; - @res = (\%raw_keys, \%def_raw_keys, "raw"); - } - } - - if (($ubi + $raw) != 1) { # double definition in section - errmsg("layout error in section [$section]"); - exit 1; - } - - return @res; -} - -sub mk_target_list($$) { - my $val = shift; - my $tmp = shift; - my $complete = 0; - - if ($val =~ m/\((.*)\)/g) { - $val = $1; - $complete = 1; - } - $val =~ s/ //g; # spaces - - @$tmp = split(/,/, $val); - - return $complete; -} - -sub copy_bytes($$$) { - my ($in, $out, $to_copy) = @_; - - while ($to_copy) { - my $buf; - my $bufsize = 1024*1024; - - $bufsize < $to_copy or $bufsize = $to_copy; - read($in, $buf, $bufsize) == $bufsize - or die "$err_prefix: image file shrunk during operation\n"; - print $out $buf; - $to_copy -= $bufsize; - } -} - -sub write_target($$) { - my ($pfi_infos, $target) = @_; - my ($pfi_info); - - infomsg("writting target pfi file \"$target.pfi\""); - if (-e "$target.pfi") { - `rm -f $target.pfi`; - } - open(FILE, ">", "$target.pfi") - or die "$err_prefix: cannot create output file: $target.pfi\n"; - binmode(FILE); - - # @FIXME sort by mode (first raw, then ubi) - # Currently this ordering is based on a string comparism. :-) - @$pfi_infos = sort {(lc $$a{'mode'}) cmp (lc $$b{'mode'})} @$pfi_infos; - - # Print all headers first - foreach $pfi_info (@$pfi_infos) { - print FILE $$pfi_info{'header'}; - } - - # Print the linked data sections - print FILE "DATA\n"; - foreach $pfi_info (@$pfi_infos) { - open(IMAGE, "<", $$pfi_info{'image'}) - or die "$err_prefix: cannot open input image: " . - "$$pfi_info{'image'}\n"; - binmode(IMAGE); - ©_bytes(\*IMAGE, \*FILE, $$pfi_info{'size'}); - close(IMAGE) or die "$err_prefix: cannot close input image: " . - "$$pfi_info{'image'}\n"; - } - - close(FILE) or die "$err_prefix: cannot close output file: $target.pfi\n"; -} - -sub process_config($) { - my $cfg = shift; - my @sections = $cfg->Sections; - my ($i, $j, $keylist, $def_keylist, $mode, $tmp, - @tlist, $complete, @pfi_infos); - - my @parameters = $cfg->Parameters("targets") or - die "$err_prefix: config file has no [targets] section\n"; - - for ($i = 0 ; $i < scalar(@parameters) ; $i++ ) { - infomsg("processing target \"$parameters[$i]\""); - @pfi_infos = (); - - # get a list of subtargets - $complete = mk_target_list($cfg->val("targets", - $parameters[$i]), \@tlist); - # build all subtargets - for ($j = 0 ; $j < scalar(@tlist) ; $j++ ) { - ($keylist, $def_keylist, $mode) - = get_section_info($cfg, $tlist[$j]); - process_section($cfg, $tlist[$j], - \@pfi_infos, - $keylist, $def_keylist, $mode); - } - - write_target(\@pfi_infos, $parameters[$i]); - } - - infomsg("success"); -} - -sub clear_files() { - # @FIXME: - # Works implicitly and Fedora seems to have removed - # the cleanup call. Thus for now, inactive. - # File::Temp::cleanup(); -} - -require 5.008_000; # Tested with version 5.8.0. -select STDOUT; $| = 1; # make STDOUT output unbuffered -select STDERR; $| = 1; # make STDERR output unbuffered - -parse_command_line(\%opts); -check_tools; -$cfg = open_cfg_file($opts{config}); -process_config($cfg); -clear_files; - -__END__ - - -=head1 NAME - -mkpfi - Using GetOpt::Long, Pod::Usage, Config::IniFiles - - -=head1 SYNOPSIS - -mkpfi [OPTIONS ...] - - - OPTION - - [--config] [--help] [--man] - - -=head1 ABSTRACT - -Perl script for generating pdd pfi files from given config files. - -=head1 OPTIONS - -=over - -=item B<--help> - -Print out brief help message. - -=item B<--usage> - -Print usage. - -=item B<--config> - -Config input file. - -=item B<--man> - -Print manual page, same as 'perldoc mkpfi'. - -=item B<--verbose> - -Be verbose. - -=back - -=head1 BUGS - -Report via MTD mailing list - - -=head1 SEE ALSO - -http://www.linux-mtd.infradead.org/ - - -=head1 AUTHOR - -Oliver Lohmann (oliloh@de.ibm.com) - -=cut diff --git a/ubi-utils/sort-me-out/Makefile b/ubi-utils/sort-me-out/Makefile deleted file mode 100644 index b8e3c96..0000000 --- a/ubi-utils/sort-me-out/Makefile +++ /dev/null @@ -1,91 +0,0 @@ -# -# Makefile -# -# Testcase for UBI pfi update. -# -# Author: Frank Haverkamp <haverkam@de.ibm.com> -# - -card = test -mkpfi_cfg = test.cfg - -# -# Some default values you might want to overwrite. Try it if you need -# it and add more if needed. Note that no real sanity checking is done -# on those values. If you do it wrong your card has no valid PDD data. -# - -PATH := $(PATH):/opt/ppc/usr/bin:../perl:.. - -dd = dd -sed = sed -bin2nand = bin2nand -ubigen = ubigen -mkpfi = mkpfi -v -pfi2bin = pfi2bin -v - -vmlinux_bin ?= test_vmlinux.bin -rootfs_bin ?= test_rootfs.bin -spl_bin ?= test_u-boot.bin -pdd_txt ?= pdd.txt - -flashtype ?= nand -pagesize ?= 2048 - -compl ?= $(card)_complete -compl_pfi ?= $(compl).pfi -compl_img ?= $(compl).img - -compl_nand2048_mif=$(compl).$(flashtype)$(pagesize).mif -compl_nand2048_img=$(compl).$(flashtype)$(pagesize).img - -all: help - -help: - @echo "Testcases for the UBI/NAND manufacturing tool-chain" - @echo "---------------------------------------------------------------" - @echo " make mif_test - Generate a mif (manufacturing " - @echo " image file)." - @echo " make bin2nand2bin_test - Create binary with ECC information" - @echo " in the OOB area. Test ECC generation" - @echo " and correction." - -mif_test: $(compl_pfi) $(compl_nand2048_mif) - -bin2nand2bin_test: - chmod a+x ./bin2nand2bin_test.sh - chmod a+x ./inject_biterror.pl - ./bin2nand2bin_test.sh - -$(compl_pfi): $(vmlinux_bin) $(rootfs_bin) $(spl_bin) - $(mkpfi) -c $(mkpfi_cfg) - -# Binary data and out of band data (OOB) -# -$(compl_nand2048_mif): $(compl_img) - $(bin2nand) -p $(pagesize) -o $(compl_nand2048_mif) $< - -# Binary data only -# -$(compl_img): $(compl_pfi) - $(pfi2bin) -j $(pdd_txt) -o $@ $< - -# -# Default data -# -# If the binary data is not available in the current working directory -# we try to create symlinks to our test data. -# -$(vmlinux_bin) $(rootfs_bin) $(spl_bin): - @echo - @echo "No $@ found, will use defaults !" - @echo - @echo "OR press CTRL-C to provide your own $@" && \ - sleep 1 && \ - $(dd) if=/dev/urandom of=$@ bs=1M count=1 - -clean: - $(RM) *.pfi *~ testblock* oob.bin - -distclean: clean - $(RM) *.bin *.mif *.oob *.img diff --git a/ubi-utils/sort-me-out/README b/ubi-utils/sort-me-out/README deleted file mode 100644 index 384322b..0000000 --- a/ubi-utils/sort-me-out/README +++ /dev/null @@ -1,68 +0,0 @@ -This directory contains various stuff that has to be cleaned up and sorted out. - -* jffs2_test.sh: this has nothing to do to UBI. And the test is quite trivial, - so it is questionable if it should not be deleted. Anyway, if we want this, - it has to be moved to mtd-utils.git/tests/fs-tests. - -* ubigen.c: this utility adds UBI headers to an image file, but does not - generate the volume table. It is probably useless, but one might find it - interesting, so we do not drop it so far and keep here. - -* bin2nand2bin_test.sh: tests nand2bin and bin2nand utilities. Should probably - go to some tests/tools-tests or something. the nand2bin and bin2nand - utilities themselves have nothing to do to UBI in general and should not sit - in ubi-utils. Should be moved somewhere like mtd-utils.git/nand-tools/ - -* f64_nor_sample.cfg, f128_nand_sample.cfg: just exampe of configuration files - for the mkpfi utility. Not too useful without any documentation. Some pfi - configuration file format documentation has to be added to mkpfi man page and - these files should probably be added there. - -* pdd.txt: not sure what is it, this is probably something specific to the - setup which is used by IBM guys (Frank, Andreas, Josh). This is probably not - of general interest and should go away. - -* run_all.sh: runns "all" test. - -* ubicrc32.pl: probably redundand as we already have a C ubicrc32 utility. - -* ubi_test.sh: some UBI testing script, should go to - mtd-utils.git/tests/ubi-tests. - -* unubi_test.sh: tests the "unubi" utility, should go somewhere like - tests/tools-tests - -* inject_biterror.pl: injects a bit error to a binary image. Does not relate to - UBI and should go to mtd-utils.git/nand-tools/ or something - -* Makefile: previously was sitting at ubi-tools/scripts and prepared fake image - files for test scripts. - -* test.cfg: mkpfi configuration file for ubi_tools_test.sh - -* ubi_tools_test.sh: similar to unubi_test.sh - -* nand2bin.c, bin2nand.c: useful utilities which should go to - mtd-utils.git/nand-tools/ - -* nandecc.c, nandecc.h: needed to compile nand2bin and bin2nand - -* nandcorr.c: seems to be unused - -* mkbootenv.c: no idea what is this about. Looks like something specific to IBM - guys's setup. - -* pfiflash*: an utility to update UBI volumes described by a pfi file on - target. Nothing wrong with it, but it seems to be rather specific to IBM - guys' environment and it should be cleaned-up. It also should be documented - better. - -* pddcustomize: not sure what is this for, seems to be IBM-specific. - -* ubimirror: not exactly sure what is this for - if it is neede, it should be - cleaned-up and moved to src/ - -* error.[ch]: strange and rather IBM-specific error messages output infrastructure. - -* libubigen-old.c: old ubigen library other tools in this directory should be - compiled with diff --git a/ubi-utils/sort-me-out/bin2nand.c b/ubi-utils/sort-me-out/bin2nand.c deleted file mode 100644 index 83f50cc..0000000 --- a/ubi-utils/sort-me-out/bin2nand.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -/* - * Create a flashable NAND image from a binary image - * - * History: - * 1.0 Initial release (tglx) - * 1.1 Understands hex and dec input parameters (tglx) - * 1.2 Generates separated OOB data, if needed. (oloh) - * 1.3 Padds data/oob to a given size. (oloh) - * 1.4 Removed argp because we want to use uClibc. - * 1.5 Minor cleanup - * 1.6 Written variable not initialized (-j did not work) (haver) - * 1.7 Made NAND ECC layout configurable (haver) - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <getopt.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> - -#include "error.h" -#include "config.h" -#include "nandecc.h" -#include "ecclayouts.h" - -#define PROGRAM_VERSION "1.7" - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - -#define CHECK_ENDP(option, endp) do { \ - if (*endp) { \ - fprintf(stderr, \ - "Parse error option \'%s\'. " \ - "No correct numeric value.\n" \ - , option); \ - exit(EXIT_FAILURE); \ - } \ -} while(0) - -typedef enum action_t { - ACT_NORMAL = 0x00000001, -} action_t; - -#define PAGESIZE 2048 -#define PADDING 0 /* 0 means, do not adjust anything */ -#define BUFSIZE 4096 - -static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" - "bin2nand - a tool for adding OOB information to a " - "binary input file.\n"; - -static const char *optionsstr = -" -c, --copyright Print copyright informatoin.\n" -" -j, --padding=<num> Padding in Byte/Mi/ki. Default = no padding\n" -" -l, --ecc-placement=<MTD,IBM> OOB placement scheme (default is IBM).\n" -" -p, --pagesize=<num> Pagesize in Byte/Mi/ki. Default = 2048\n" -" -o, --output=<fname> Output filename. Interleaved Data/OOB if\n" -" output-oob not specified.\n" -" -q, --output-oob=<fname> Write OOB data in separate file.\n" -" -?, --help Give this help list\n" -" --usage Give a short usage message\n" -" -V, --version Print program version\n"; - -static const char *usage = -"Usage: bin2nand [-c?V] [-j <num>] [-p <num>] [-o <fname>] [-q <fname>]\n" -" [--copyright] [--padding=<num>] [--pagesize=<num>]\n" -" [--output=<fname>] [--output-oob=<fname>] [--help] [--usage]\n" -" [--version]\n"; - -struct option long_options[] = { - { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, - { .name = "padding", .has_arg = 1, .flag = NULL, .val = 'j' }, - { .name = "pagesize", .has_arg = 1, .flag = NULL, .val = 'p' }, - { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, - { .name = "output-oob", .has_arg = 1, .flag = NULL, .val = 'q' }, - { .name = "ecc-layout", .has_arg = 1, .flag = NULL, .val = 'l' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, - { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0} -}; - -#define __unused __attribute__((unused)) -static const char copyright [] __unused = "Copyright IBM Corp. 2007"; - -struct args { - action_t action; - - size_t pagesize; - size_t oobsize; - size_t padding; - - FILE* fp_in; - const char *file_out_data; /* Either: Data and OOB interleaved - or plain data */ - const char *file_out_oob; /* OOB Data only. */ - struct nand_ecclayout *nand_oob; - - /* special stuff needed to get additional arguments */ - char *arg1; - char **options; /* [STRING...] */ -}; - - -static int ustrtoull(const char *cp, char **endp, unsigned int base) -{ - unsigned long long res = strtoull(cp, endp, base); - - switch (**endp) { - case 'G': - res *= 1024; - case 'M': - res *= 1024; - case 'k': - case 'K': - res *= 1024; - /* "Ki", "ki", "Mi" or "Gi" are to be used. */ - if ((*endp)[1] == 'i') - (*endp) += 2; - } - return res; -} - -static int -parse_opt(int argc, char **argv, struct args *args) -{ - const char *ecc_layout = NULL; - unsigned int i, oob_idx = 0; - char* endp; - - while (1) { - int key; - - key = getopt_long(argc, argv, "cj:l:p:o:q:?V", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'p': /* pagesize */ - args->pagesize = (size_t) - ustrtoull(optarg, &endp, 0); - CHECK_ENDP("p", endp); - break; - case 'j': /* padding */ - args->padding = (size_t) - ustrtoull(optarg, &endp, 0); - CHECK_ENDP("j", endp); - break; - case 'o': /* output */ - args->file_out_data = optarg; - break; - case 'q': /* output oob */ - args->file_out_oob = optarg; - break; - case 'l': /* --ecc-layout=<...> */ - ecc_layout = optarg; - break; - case '?': /* help */ - printf("%s%s", doc, optionsstr); - exit(0); - break; - case 'V': - printf("%s\n", PROGRAM_VERSION); - exit(0); - break; - case 'c': - printf("%s\n", copyright); - exit(0); - default: - printf("%s", usage); - exit(-1); - } - } - - if (optind < argc) { - args->fp_in = fopen(argv[optind++], "rb"); - if ((args->fp_in) == NULL) { - err_quit("Cannot open file %s for input\n", - argv[optind++]); - } - } - - switch (args->pagesize) { - case 512: args->oobsize = 16; oob_idx = 0; break; - case 2048: args->oobsize = 64; oob_idx = 1; break; - default: - err_msg("Unsupported page size: %d\n", args->pagesize); - return -EINVAL; - } - - /* Figure out correct oob layout if it differs from default */ - if (ecc_layout) { - for (i = 0; i < ARRAY_SIZE(oob_placement); i++) - if (strcmp(ecc_layout, oob_placement[i].name) == 0) - args->nand_oob = - oob_placement[i].nand_oob[oob_idx]; - } - return 0; -} - -static int -process_page(struct args *args, uint8_t *buf, FILE *fp_data, FILE *fp_oob, - size_t *written) -{ - int eccpoi; - size_t i; - uint8_t oobbuf[64]; - uint8_t ecc_code[3] = { 0, }; /* temp */ - - /* Calculate ECC for each subpage of 256 bytes */ - memset(oobbuf, 0xff, sizeof(oobbuf)); - for (eccpoi = 0, i = 0; i < args->pagesize; i += 256, eccpoi += 3) { - int j; - nand_calculate_ecc(&buf[i], ecc_code); - for (j = 0; j < 3; j++) - oobbuf[args->nand_oob->eccpos[eccpoi + j]] = ecc_code[j]; - } - - /* write data */ - *written += fwrite(buf, 1, args->pagesize, fp_data); - - /* either separate oob or interleave with data */ - if (fp_oob) { - i = fwrite(oobbuf, 1, args->oobsize, fp_oob); - if (ferror(fp_oob)) { - err_msg("IO error\n"); - return -EIO; - } - } - else { - i = fwrite(oobbuf, 1, args->oobsize, fp_data); - if (ferror(fp_data)) { - err_msg("IO error\n"); - return -EIO; - } - } - - return 0; -} - -int main (int argc, char** argv) -{ - int rc = -1; - int res = 0; - size_t written = 0, read; - struct args args = { - .action = ACT_NORMAL, - .pagesize = PAGESIZE, - .padding = PADDING, - .fp_in = NULL, - .file_out_data = NULL, - .file_out_oob = NULL, - .nand_oob = &ibm_nand_oob_64, - }; - - FILE* fp_out_data = stdout; - FILE* fp_out_oob = NULL; - - parse_opt(argc, argv, &args); - - uint8_t* buf = calloc(1, BUFSIZE); - if (!buf) { - err_quit("Cannot allocate page buffer.\n"); - } - - if (!args.fp_in) { - err_msg("No input image specified!\n"); - goto err; - } - - if (args.file_out_data) { - fp_out_data = fopen(args.file_out_data, "wb"); - if (fp_out_data == NULL) { - err_sys("Cannot open file %s for output\n", - args.file_out_data); - goto err; - } - } - - if (args.file_out_oob) { - fp_out_oob = fopen(args.file_out_oob, "wb"); - if (fp_out_oob == NULL) { - err_sys("Cannot open file %s for output\n", - args.file_out_oob); - goto err; - } - } - - - while(1) { - read = fread(buf, 1, args.pagesize, args.fp_in); - if (feof(args.fp_in) && read == 0) - break; - - if (read < args.pagesize) { - err_msg("Image not page aligned\n"); - goto err; - } - - if (ferror(args.fp_in)) { - err_msg("Read error\n"); - goto err; - } - - res = process_page(&args, buf, fp_out_data, fp_out_oob, - &written); - if (res != 0) - goto err; - } - - while (written < args.padding) { - memset(buf, 0xff, args.pagesize); - res = process_page(&args, buf, fp_out_data, fp_out_oob, - &written); - if (res != 0) - goto err; - } - - rc = 0; -err: - free(buf); - - if (args.fp_in) - fclose(args.fp_in); - - if (fp_out_oob) - fclose(fp_out_oob); - - if (fp_out_data && fp_out_data != stdout) - fclose(fp_out_data); - - if (rc != 0) { - err_msg("Error during conversion. rc: %d\n", rc); - if (args.file_out_data) - remove(args.file_out_data); - if (args.file_out_oob) - remove(args.file_out_oob); - } - return rc; -} diff --git a/ubi-utils/sort-me-out/bin2nand2bin_test.sh b/ubi-utils/sort-me-out/bin2nand2bin_test.sh deleted file mode 100755 index 51f048c..0000000 --- a/ubi-utils/sort-me-out/bin2nand2bin_test.sh +++ /dev/null @@ -1,216 +0,0 @@ -#!/bin/sh -# -# Version: 1.1 -# Author: Frank Haverkamp <haver@vnet.ibm.com> -# -# Testcase for nand2bin and bin2nand. Generate testdata and inject -# biterrors. Convert data back and compare with original data. -# -# Conversion: -# bin -> bin2nand -> mif -> nand2bin -> img -# - -inject_biterror=./inject_biterror.pl -pagesize=2048 -oobsize=64 - -# Create test data -dd if=/dev/urandom of=testblock.bin bs=131072 count=1 - -for layout in IBM MTD ; do - echo "*** Simple test with $layout layout ..." - - echo -n "Convert bin to mif ... " - bin2nand -l$layout --pagesize=${pagesize} -o testblock.mif testblock.bin - if [ $? -ne "0" ]; then - echo "failed!" - exit 1 - else - echo "ok" - fi - - echo -n "Convert mif to bin ... " - nand2bin -l$layout --pagesize=${pagesize} -o testblock.img testblock.mif - if [ $? -ne "0" ]; then - echo "failed!" - exit 1 - else - echo "ok" - fi - - echo -n "Comparing data ... " - diff testblock.bin testblock.img - if [ $? -ne "0" ]; then - echo "failed!" - exit 1 - else - echo "ok" - fi -done - -echo "*** Test conversion without bitflips ..." - -echo -n "Convert bin to mif ... " -bin2nand --pagesize=${pagesize} -o testblock.mif testblock.bin -if [ $? -ne "0" ]; then - echo "failed!" - exit 1 -else - echo "ok" -fi - -echo -n "Convert mif to bin ... " -nand2bin --pagesize=${pagesize} -o testblock.img testblock.mif -if [ $? -ne "0" ]; then - echo "failed!" - exit 1 -else - echo "ok" -fi - -echo -n "Comparing data ... " -diff testblock.bin testblock.img -if [ $? -ne "0" ]; then - echo "failed!" - exit 1 -else - echo "ok" -fi - -echo "*** Test conversion with uncorrectable ECC erors ..." -echo -n "Inject biterror at offset $ioffs ... " -${inject_biterror} --offset=0 --bitmask=0x81 \ - --input=testblock.mif \ - --output=testblock_bitflip.mif -if [ $? -ne "0" ]; then - echo "failed!" - exit 1 -else - echo "ok" -fi - -echo "Convert mif to bin ... " -rm testblock.img -nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \ - testblock_bitflip.mif -if [ $? -ne "0" ]; then - echo "failed!" - exit 1 -else - echo "ok" -fi - -echo -n "Comparing data, must fail due to uncorrectable ECC ... " -diff testblock.bin testblock.img -if [ $? -ne "0" ]; then - echo "ok" # Must fail! -else - echo "failed!" - exit 1 -fi - -echo "*** Test bitflips in data ... " -for offs in `seq 0 255` ; do - - cp testblock.mif testblock_bitflip.mif - - for xoffs in 0 256 512 768 ; do - let ioffs=$offs+$xoffs - - cp testblock_bitflip.mif testblock_bitflip_tmp.mif - echo -n "Inject biterror at offset $ioffs ... " - ${inject_biterror} --offset=${ioffs} --bitmask=0x01 \ - --input=testblock_bitflip_tmp.mif \ - --output=testblock_bitflip.mif - if [ $? -ne "0" ]; then - echo "failed!" - exit 1 - else - echo "ok" - fi - done - - echo "Convert mif to bin ... " - rm testblock.img - nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \ - testblock_bitflip.mif - if [ $? -ne "0" ]; then - echo "failed!" - exit 1 - else - echo "ok" - fi - - echo -n "Comparing data ... " - diff testblock.bin testblock.img - if [ $? -ne "0" ]; then - hexdump testblock.bin > testblock.bin.txt - hexdump testblock.img > testblock.img.txt - echo "Use tkdiff testblock.bin.txt testblock.img.txt to compare" - echo "failed!" - exit 1 - else - echo "ok" - fi - - # Without correction - echo "Convert mif to bin ... " - rm testblock.img - nand2bin --pagesize=${pagesize} -o testblock.img \ - testblock_bitflip.mif - if [ $? -ne "0" ]; then - echo "failed!" - exit 1 - else - echo "ok" - fi - - echo -n "Comparing data must differ, correction is disabled ... " - diff testblock.bin testblock.img - if [ $? -ne "0" ]; then - echo "ok" # must fail - else - echo "failed!" - exit 1 - fi -done - -echo "*** Test bitflips in OOB data ... " -for offs in `seq 0 $oobsize` ; do - - let ioffs=$pagesize+$offs - - echo -n "Inject biterror at offset $ioffs ... " - ${inject_biterror} --offset=${ioffs} --bitmask=0x01 \ - --input=testblock.mif \ - --output=testblock_bitflip.mif - if [ $? -ne "0" ]; then - echo "failed!" - exit 1 - else - echo "ok" - fi - - echo "Convert mif to bin ... " - rm testblock.img - nand2bin --correct-ecc --pagesize=${pagesize} -o testblock.img \ - testblock_bitflip.mif - if [ $? -ne "0" ]; then - echo "failed!" - exit 1 - else - echo "ok" - fi - - echo -n "Comparing data ... " - diff testblock.bin testblock.img - if [ $? -ne "0" ]; then - hexdump testblock.bin > testblock.bin.txt - hexdump testblock.img > testblock.img.txt - echo "Use tkdiff testblock.bin.txt testblock.img.txt to compare" - echo "failed!" - exit 1 - else - echo "ok" - fi -done diff --git a/ubi-utils/sort-me-out/bootenv.c b/ubi-utils/sort-me-out/bootenv.c deleted file mode 100644 index a6dd4de..0000000 --- a/ubi-utils/sort-me-out/bootenv.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> -#include <netinet/in.h> -#include <sys/stat.h> -#include <bootenv.h> - -#include "hashmap.h" -#include "error.h" - -#include <mtd/ubi-header.h> -#include "crc32.h" - -#define ubi_unused __attribute__((unused)) - -#define BOOTENV_MAXLINE 512 /* max line size of a bootenv.txt file */ - -/* Structures */ -struct bootenv { - hashmap_t map; ///< Pointer to hashmap which holds data structure. -}; - -struct bootenv_list { - hashmap_t head; ///< Pointer to list which holds the data structure. -}; - -/** - * @brief Remove the '\n' from a given line. - * @param line Input/Output line. - * @param size Size of the line. - * @param fp File Pointer. - * @return 0 - * @return or error - */ -static int -remove_lf(char *line, size_t size, FILE* fp) -{ - size_t i; - - for (i = 0; i < size; i++) { - if (line[i] == '\n') { - line[i] = '\0'; - return 0; - } - } - - if (!feof(fp)) { - return BOOTENV_EINVAL; - } - - return 0; -} - -/** - * @brief Determine if a line contains only WS. - * @param line The line to process. - * @param size Size of input line. - * @return 1 Yes, only WS. - * @return 0 No, contains data. - */ -static int -is_ws(const char *line, size_t size) -{ - size_t i = 0; - - while (i < size) { - switch (line[i]) { - case '\n': - return 1; - case '#': - return 1; - case ' ': - i++; - continue; - case '\t': - i++; - continue; - default: /* any other char -> no cmnt */ - return 0; - } - } - - return 0; -} - - -/* ------------------------------------------------------------------------- */ - -/** - * @brief Build a list from a comma seperated value string. - * @param list Pointer to hashmap structure which shall store - * the list. - * @param value Comma seperated value string. - * @return 0 - * @return or error. - */ -static int -build_list_definition(hashmap_t list, const char *value) -{ - int rc = 0; - char *str = NULL; - char *ptr = NULL; - size_t len, i, j; - - /* str: val1,val2 , val4,...,valN */ - len = strlen(value); - str = (char*) malloc((len+1) * sizeof(char)); - - /* 1. reformat string: remove spaces */ - for (i = 0, j = 0; i < len; i++) { - if (value[i] == ' ') - continue; - - str[j] = value[i]; - j++; - } - str[j] = '\0'; - - /* str: val1,val2,val4,...,valN\0*/ - /* 2. replace ',' seperator with '\0' */ - len = strlen(str); - for (i = 0; i < len; i++) { - if (str[i] == ',') { - str[i] = '\0'; - } - } - - /* str: val1\0val2\0val4\0...\0valN\0*/ - /* 3. insert definitions into a hash map, using it like a list */ - i = j = 0; - ptr = str; - while (((i = strlen(ptr)) > 0) && (j < len)) { - rc = hashmap_add(list, ptr, ""); - if (rc != 0) { - free(str); - return rc; - } - j += i+1; - if (j < len) - ptr += i+1; - } - - free(str); - return rc; -} - -/** - * @brief Extract a key value pair and add it to a hashmap - * @param str Input string which contains a key value pair. - * @param env The updated handle which contains the new pair. - * @return 0 - * @return or error - * @note The input string format is: "key=value" - */ -static int -extract_pair(const char *str, bootenv_t env) -{ - int rc = 0; - char *key = NULL; - char *val = NULL; - - key = strdup(str); - if (key == NULL) - return -ENOMEM; - - val = strstr(key, "="); - if (val == NULL) { - rc = BOOTENV_EBADENTRY; - goto err; - } - - *val = '\0'; /* split strings */ - val++; - - rc = bootenv_set(env, key, val); - - err: - free(key); - return rc; -} - -int -bootenv_destroy(bootenv_t* env) -{ - int rc = 0; - - if (env == NULL || *env == NULL) - return -EINVAL; - - bootenv_t tmp = *env; - - rc = hashmap_free(tmp->map); - if (rc != 0) - return rc; - - free(tmp); - return rc; -} - -int -bootenv_create(bootenv_t* env) -{ - bootenv_t res; - res = (bootenv_t) calloc(1, sizeof(struct bootenv)); - - if (res == NULL) - return -ENOMEM; - - res->map = hashmap_new(); - - if (res->map == NULL) { - free(res); - return -ENOMEM; - } - - *env = res; - - return 0; -} - - -/** - * @brief Read a formatted buffer and scan it for valid bootenv - * key/value pairs. Add those pairs into a hashmap. - * @param env Hashmap which shall be used to hold the data. - * @param buf Formatted buffer. - * @param size Size of the buffer. - * @return 0 - * @return or error - */ -static int -rd_buffer(bootenv_t env, const char *buf, size_t size) -{ - const char *curr = buf; /* ptr to current key/value pair */ - uint32_t i, j; /* current length, chars processed */ - - if (buf[size - 1] != '\0') /* must end in '\0' */ - return BOOTENV_EFMT; - - for (j = 0; j < size; j += i, curr += i) { - /* strlen returns the size of the string upto - but not including the null terminator; - adding 1 to account for '\0' */ - i = strlen(curr) + 1; - - if (i == 1) - return 0; /* no string found */ - - if (extract_pair(curr, env) != 0) - return BOOTENV_EINVAL; - } - - return 0; -} - - -int -bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t* ret_crc) -{ - int rc; - char *buf = NULL; - size_t i = 0; - uint32_t crc32_table[256]; - - if ((fp == NULL) || (env == NULL)) - return -EINVAL; - - /* allocate temp buffer */ - buf = (char*) calloc(1, size * sizeof(char)); - if (buf == NULL) - return -ENOMEM; - - /* FIXME Andreas, please review this I removed size-1 and - * replaced it by just size, I saw the kernel image starting - * with a 0x0060.... and not with the 0x60.... what it should - * be. Is this a tools problem or is it a problem here where - * fp is moved not to the right place due to the former size-1 - * here. - */ - while((i < size) && (!feof(fp))) { - int c = fgetc(fp); - if (c == EOF) { - /* FIXME isn't this dangerous, to update - the boot envs with incomplete data? */ - buf[i++] = '\0'; - break; /* we have enough */ - } - if (ferror(fp)) { - rc = -EIO; - goto err; - } - - buf[i++] = (char)c; - } - - /* calculate crc to return */ - if (ret_crc != NULL) { - init_crc32_table(crc32_table); - *ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size); - } - - /* transfer to hashmap */ - rc = rd_buffer(env, buf, size); - -err: - free(buf); - return rc; -} - - -/** - * If we have a single file containing the boot-parameter size should - * be specified either as the size of the file or as BOOTENV_MAXSIZE. - * If the bootparameter are in the middle of a file we need the exact - * length of the data. - */ -int -bootenv_read(FILE* fp, bootenv_t env, size_t size) -{ - return bootenv_read_crc(fp, env, size, NULL); -} - - -int -bootenv_read_txt(FILE* fp, bootenv_t env) -{ - int rc = 0; - char *buf = NULL; - char *line = NULL; - char *lstart = NULL; - char *curr = NULL; - size_t len; - size_t size; - - if ((fp == NULL) || (env == NULL)) - return -EINVAL; - - size = BOOTENV_MAXSIZE; - - /* allocate temp buffers */ - buf = (char*) calloc(1, size * sizeof(char)); - lstart = line = (char*) calloc(1, size * sizeof(char)); - if ((buf == NULL) || (line == NULL)) { - rc = -ENOMEM; - goto err; - } - - curr = buf; - while ((line = fgets(line, size, fp)) != NULL) { - if (is_ws(line, size)) { - continue; - } - rc = remove_lf(line, BOOTENV_MAXSIZE, fp); - if (rc != 0) { - goto err; - } - - /* copy new line to binary buffer */ - len = strlen(line); - if (len > size) { - rc = -EFBIG; - goto err; - } - size -= len; /* track remaining space */ - - memcpy(curr, line, len); - curr += len + 1; /* for \0 seperator */ - } - - rc = rd_buffer(env, buf, BOOTENV_MAXSIZE); -err: - if (buf != NULL) - free(buf); - if (lstart != NULL) - free(lstart); - return rc; -} - -static int -fill_output_buffer(bootenv_t env, char *buf, size_t buf_size_max ubi_unused, - size_t *written) -{ - int rc = 0; - size_t keys_size, i; - size_t wr = 0; - const char **keys = NULL; - const char *val = NULL; - - rc = bootenv_get_key_vector(env, &keys_size, 1, &keys); - if (rc != 0) - goto err; - - for (i = 0; i < keys_size; i++) { - if (wr > BOOTENV_MAXSIZE) { - rc = -ENOSPC; - goto err; - } - - rc = bootenv_get(env, keys[i], &val); - if (rc != 0) - goto err; - - wr += snprintf(buf + wr, BOOTENV_MAXSIZE - wr, - "%s=%s", keys[i], val); - wr++; /* for \0 */ - } - - *written = wr; - -err: - if (keys != NULL) - free(keys); - - return rc; -} - -int -bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc) -{ - int rc = 0; - size_t size = 0; - char *buf = NULL; - uint32_t crc32_table[256]; - - if ((fp == NULL) || (env == NULL)) - return -EINVAL; - - buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char)); - if (buf == NULL) - return -ENOMEM; - - - rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, &size); - if (rc != 0) - goto err; - - /* calculate crc to return */ - if (ret_crc != NULL) { - init_crc32_table(crc32_table); - *ret_crc = clc_crc32(crc32_table, UBI_CRC32_INIT, buf, size); - } - - if (fwrite(buf, size, 1, fp) != 1) { - rc = -EIO; - goto err; - } - -err: - if (buf != NULL) - free(buf); - return rc; -} - -int -bootenv_write(FILE* fp, bootenv_t env) -{ - return bootenv_write_crc(fp, env, NULL); -} - -int -bootenv_compare(bootenv_t first, bootenv_t second) -{ - int rc; - size_t written_first, written_second; - char *buf_first, *buf_second; - - if (first == NULL || second == NULL) - return -EINVAL; - - buf_first = malloc(BOOTENV_MAXSIZE); - if (!buf_first) - return -ENOMEM; - buf_second = malloc(BOOTENV_MAXSIZE); - if (!buf_second) { - rc = -ENOMEM; - goto err; - } - - rc = fill_output_buffer(first, buf_first, BOOTENV_MAXSIZE, - &written_first); - if (rc < 0) - goto err; - rc = fill_output_buffer(second, buf_second, BOOTENV_MAXSIZE, - &written_second); - if (rc < 0) - goto err; - - if (written_first != written_second) { - rc = 1; - goto err; - } - - rc = memcmp(buf_first, buf_second, written_first); - if (rc != 0) { - rc = 2; - goto err; - } - -err: - if (buf_first) - free(buf_first); - if (buf_second) - free(buf_second); - - return rc; -} - -int -bootenv_size(bootenv_t env, size_t *size) -{ - int rc = 0; - char *buf = NULL; - - if (env == NULL) - return -EINVAL; - - buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char)); - if (buf == NULL) - return -ENOMEM; - - rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, size); - if (rc != 0) - goto err; - -err: - if (buf != NULL) - free(buf); - return rc; -} - -int -bootenv_write_txt(FILE* fp, bootenv_t env) -{ - int rc = 0; - size_t size, wr, i; - const char **keys = NULL; - const char *key = NULL; - const char *val = NULL; - - if ((fp == NULL) || (env == NULL)) - return -EINVAL; - - rc = bootenv_get_key_vector(env, &size, 1, &keys); - if (rc != 0) - goto err; - - for (i = 0; i < size; i++) { - key = keys[i]; - rc = bootenv_get(env, key, &val); - if (rc != 0) - goto err; - - wr = fprintf(fp, "%s=%s\n", key, val); - if (wr != strlen(key) + strlen(val) + 2) { - rc = -EIO; - goto err; - } - } - -err: - if (keys != NULL) - free(keys); - return rc; -} - -int -bootenv_valid(bootenv_t env ubi_unused) -{ - /* @FIXME No sanity check implemented. */ - return 0; -} - -int -bootenv_copy_bootenv(bootenv_t in, bootenv_t *out) -{ - int rc = 0; - const char *tmp = NULL; - const char **keys = NULL; - size_t vec_size, i; - - if ((in == NULL) || (out == NULL)) - return -EINVAL; - - /* purge output var for sure... */ - rc = bootenv_destroy(out); - if (rc != 0) - return rc; - - /* create the new map */ - rc = bootenv_create(out); - if (rc != 0) - goto err; - - /* get the key list from the input map */ - rc = bootenv_get_key_vector(in, &vec_size, 0, &keys); - if (rc != 0) - goto err; - - if (vec_size != hashmap_size(in->map)) { - rc = BOOTENV_ECOPY; - goto err; - } - - /* make a deep copy of the hashmap */ - for (i = 0; i < vec_size; i++) { - rc = bootenv_get(in, keys[i], &tmp); - if (rc != 0) - goto err; - - rc = bootenv_set(*out, keys[i], tmp); - if (rc != 0) - goto err; - } - -err: - if (keys != NULL) - free(keys); - - return rc; -} - -/* ------------------------------------------------------------------------- */ - - -int -bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res, - int *warnings, char *err_buf ubi_unused, - size_t err_buf_size ubi_unused) -{ - bootenv_list_t l_old = NULL; - bootenv_list_t l_new = NULL; - const char *pdd_old = NULL; - const char *pdd_new = NULL; - const char *tmp = NULL; - const char **vec_old = NULL; - const char **vec_new = NULL; - const char **pdd_up_vec = NULL; - size_t vec_old_size, vec_new_size, pdd_up_vec_size, i; - int rc = 0; - - if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL)) - return -EINVAL; - - /* get the pdd strings, e.g.: - * pdd_old=a,b,c - * pdd_new=a,c,d,e */ - rc = bootenv_get(env_old, "pdd", &pdd_old); - if (rc != 0) - goto err; - rc = bootenv_get(env_new, "pdd", &pdd_new); - if (rc != 0) - goto err; - - /* put it into a list and then convert it to an vector */ - rc = bootenv_list_create(&l_old); - if (rc != 0) - goto err; - rc = bootenv_list_create(&l_new); - if (rc != 0) - goto err; - - rc = bootenv_list_import(l_old, pdd_old); - if (rc != 0) - goto err; - - rc = bootenv_list_import(l_new, pdd_new); - if (rc != 0) - goto err; - - rc = bootenv_list_to_vector(l_old, &vec_old_size, &vec_old); - if (rc != 0) - goto err; - - rc = bootenv_list_to_vector(l_new, &vec_new_size, &vec_new); - if (rc != 0) - goto err; - - rc = bootenv_copy_bootenv(env_new, env_res); - if (rc != 0) - goto err; - - /* calculate the update vector between the old and new pdd */ - pdd_up_vec = hashmap_get_update_key_vector(vec_old, vec_old_size, - vec_new, vec_new_size, &pdd_up_vec_size); - - if (pdd_up_vec == NULL) { - rc = -ENOMEM; - goto err; - } - - if (pdd_up_vec_size != 0) { - /* need to warn the user about the unset of - * some pdd/bootenv values */ - *warnings = BOOTENV_WPDD_STRING_DIFFERS; - - /* remove all entries in the new bootenv load */ - for (i = 0; i < pdd_up_vec_size; i++) { - bootenv_unset(*env_res, pdd_up_vec[i]); - } - } - - /* generate the keep array and copy old pdd values to new bootenv */ - for (i = 0; i < vec_old_size; i++) { - rc = bootenv_get(env_old, vec_old[i], &tmp); - if (rc != 0) { - rc = BOOTENV_EPDDINVAL; - goto err; - } - rc = bootenv_set(*env_res, vec_old[i], tmp); - if (rc != 0) { - goto err; - } - } - /* put the old pdd string into the result map */ - rc = bootenv_set(*env_res, "pdd", pdd_old); - if (rc != 0) { - goto err; - } - - -err: - if (vec_old != NULL) - free(vec_old); - if (vec_new != NULL) - free(vec_new); - if (pdd_up_vec != NULL) - free(pdd_up_vec); - - bootenv_list_destroy(&l_old); - bootenv_list_destroy(&l_new); - return rc; -} - - -int -bootenv_pdd_overwrite(bootenv_t env_old, bootenv_t env_new, - bootenv_t *env_res, int *warnings ubi_unused, - char *err_buf ubi_unused, size_t err_buf_size ubi_unused) -{ - if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL)) - return -EINVAL; - - return bootenv_copy_bootenv(env_new, env_res); -} - -int -bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res, - int *warnings ubi_unused, char *err_buf, size_t err_buf_size) -{ - if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL)) - return -EINVAL; - - snprintf(err_buf, err_buf_size, "The PDD merge operation is not " - "implemented. Contact: <oliloh@de.ibm.com>"); - - return BOOTENV_ENOTIMPL; -} - -/* ------------------------------------------------------------------------- */ - -int -bootenv_get(bootenv_t env, const char *key, const char **value) -{ - if (env == NULL) - return -EINVAL; - - *value = hashmap_lookup(env->map, key); - if (*value == NULL) - return BOOTENV_ENOTFOUND; - - return 0; -} - -int -bootenv_get_num(bootenv_t env, const char *key, uint32_t *value) -{ - char *endptr = NULL; - const char *str; - - if (env == NULL) - return 0; - - str = hashmap_lookup(env->map, key); - if (!str) - return -EINVAL; - - *value = strtoul(str, &endptr, 0); - - if (*endptr == '\0') { - return 0; - } - - return -EINVAL; -} - -int -bootenv_set(bootenv_t env, const char *key, const char *value) -{ - if (env == NULL) - return -EINVAL; - - return hashmap_add(env->map, key, value); -} - -int -bootenv_unset(bootenv_t env, const char *key) -{ - if (env == NULL) - return -EINVAL; - - return hashmap_remove(env->map, key); -} - -int -bootenv_get_key_vector(bootenv_t env, size_t* size, int sort, - const char ***vector) -{ - if ((env == NULL) || (size == NULL)) - return -EINVAL; - - *vector = hashmap_get_key_vector(env->map, size, sort); - - if (*vector == NULL) - return -EINVAL; - - return 0; -} - -int -bootenv_dump(bootenv_t env) -{ - if (env == NULL) - return -EINVAL; - - return hashmap_dump(env->map); -} - -int -bootenv_list_create(bootenv_list_t *list) -{ - bootenv_list_t res; - res = (bootenv_list_t) calloc(1, sizeof(struct bootenv_list)); - - if (res == NULL) - return -ENOMEM; - - res->head = hashmap_new(); - - if (res->head == NULL) { - free(res); - return -ENOMEM; - } - - *list = res; - return 0; -} - -int -bootenv_list_destroy(bootenv_list_t *list) -{ - int rc = 0; - - if (list == NULL) - return -EINVAL; - - bootenv_list_t tmp = *list; - if (tmp == 0) - return 0; - - rc = hashmap_free(tmp->head); - if (rc != 0) - return rc; - - free(tmp); - *list = NULL; - return 0; -} - -int -bootenv_list_import(bootenv_list_t list, const char *str) -{ - if (list == NULL) - return -EINVAL; - - return build_list_definition(list->head, str); -} - -int -bootenv_list_export(bootenv_list_t list, char **string) -{ - size_t size, i, j, bufsize, tmp, rc = 0; - const char **items; - - if (list == NULL) - return -EINVAL; - - bufsize = BOOTENV_MAXLINE; - char *res = (char*) malloc(bufsize * sizeof(char)); - if (res == NULL) - return -ENOMEM; - - rc = bootenv_list_to_vector(list, &size, &items); - if (rc != 0) { - goto err; - } - - j = 0; - for (i = 0; i < size; i++) { - tmp = strlen(items[i]); - if (j >= bufsize) { - bufsize += BOOTENV_MAXLINE; - res = (char*) realloc(res, bufsize * sizeof(char)); - if (res == NULL) { - rc = -ENOMEM; - goto err; - } - } - memcpy(res + j, items[i], tmp); - j += tmp; - if (i < (size - 1)) { - res[j] = ','; - j++; - } - } - j++; - res[j] = '\0'; - free(items); - *string = res; - return 0; -err: - free(items); - return rc; -} - -int -bootenv_list_add(bootenv_list_t list, const char *item) -{ - if ((list == NULL) || (item == NULL)) - return -EINVAL; - - return hashmap_add(list->head, item, ""); -} - -int -bootenv_list_remove(bootenv_list_t list, const char *item) -{ - if ((list == NULL) || (item == NULL)) - return -EINVAL; - - return hashmap_remove(list->head, item); -} - -int -bootenv_list_is_in(bootenv_list_t list, const char *item) -{ - if ((list == NULL) || (item == NULL)) - return -EINVAL; - - return hashmap_lookup(list->head, item) != NULL ? 1 : 0; -} - -int -bootenv_list_to_vector(bootenv_list_t list, size_t *size, const char ***vector) -{ - if ((list == NULL) || (size == NULL)) - return -EINVAL; - - *vector = hashmap_get_key_vector(list->head, size, 1); - if (*vector == NULL) - return -ENOMEM; - - return 0; -} - -int -bootenv_list_to_num_vector(bootenv_list_t list, size_t *size, - uint32_t **vector) -{ - int rc = 0; - size_t i; - uint32_t* res = NULL; - char *endptr = NULL; - const char **a = NULL; - - rc = bootenv_list_to_vector(list, size, &a); - if (rc != 0) - goto err; - - res = (uint32_t*) malloc (*size * sizeof(uint32_t)); - if (!res) - goto err; - - for (i = 0; i < *size; i++) { - res[i] = strtoul(a[i], &endptr, 0); - if (*endptr != '\0') - goto err; - } - - if (a) - free(a); - *vector = res; - return 0; - -err: - if (a) - free(a); - if (res) - free(res); - return rc; -} diff --git a/ubi-utils/sort-me-out/bootenv.h b/ubi-utils/sort-me-out/bootenv.h deleted file mode 100644 index 8fecdbf..0000000 --- a/ubi-utils/sort-me-out/bootenv.h +++ /dev/null @@ -1,434 +0,0 @@ -#ifndef __BOOTENV_H__ -#define __BOOTENV_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdio.h> /* FILE */ -#include <stdint.h> -#include <pfiflash.h> - -/* DOXYGEN DOCUMENTATION */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file bootenv.h - * @author oliloh@de.ibm.com - * @version 1.3 - * - * 1.3 Some renaming - */ - -/** - * @mainpage Usage - * - * @section intro Introduction - * This library provides all functionality to handle with the so-called - * platform description data (PDD) and the bootparameters defined in - * U-Boot. It is able to apply the defined PDD operations in PDD update - * scenarios. For more information about the PDD and bootparameter - * environment "bootenv" confer the PDD documentation. - * - * @section ret Return codes - * This library defines some return codes which will be delivered classified - * as warnings or errors. See the "Defines" section for details and numeric - * values. - * - * @section benv Bootenv format description - * There are two different input formats: - * - text files - * - binary files - * - * @subsection txt Text Files - * Text files have to be specified like: - * @verbatim key1=value1,value2,value7\n key2=value55,value1\n key4=value1\n@endverbatim - * - * @subsection bin Binary files - * Binary files have to be specified like: - * @verbatim<CRC32-bit>key1=value1,value2,value7\0key2=value55,value1\0... @endverbatim - * You can confer the U-Boot documentation for more details. - * - * @section benvlists Bootenv lists format description. - * Values referenced in the preceeding subsection can be - * defined like lists: - * @verbatim value1,value2,value3 @endverbatim - * There are some situation where a conversion of a comma - * seperated list can be useful, e.g. to get a list - * of defined PDD entries. - */ - -#define BOOTENV_MAXSIZE (1024 * 100) /* max 100kiB space for bootenv */ - -/** - * @def BOOTENV_ECRC - * @brief Given binary file is to large. - * @def BOOTENV_EFMT - * @brief Given bootenv section has an invalid format - * @def BOOTENV_EBADENTRY - * @brief Bad entry in the bootenv section. - * @def BOOTENV_EINVAL - * @brief Invalid bootenv defintion. - * @def BOOTENV_ENOPDD - * @brief Given bootenv sectoin has no PDD defintion string (pdd=...). - * @def BOOTENV_EPDDINVAL - * @brief Given bootenv section has an invalid PDD defintion. - * @def BOOTENV_ENOTIMPL - * @brief Functionality not implemented. - * @def BOOTENV_ECOPY - * @brief Bootenv memory copy error - * @def BOOTENV_ENOTFOUND - * @brief Given key has has no value. - * @def BOOTENV_EMAX - * @brief Highest error value. - */ -#define BOOTENV_ETOOBIG 1 -#define BOOTENV_EFMT 2 -#define BOOTENV_EBADENTRY 3 -#define BOOTENV_EINVAL 4 -#define BOOTENV_ENOPDD 5 -#define BOOTENV_EPDDINVAL 6 -#define BOOTENV_ENOTIMPL 7 -#define BOOTENV_ECOPY 8 -#define BOOTENV_ENOTFOUND 9 -#define BOOTENV_EMAX 10 - -/** - * @def BOOTENV_W - * @brief A warning which is handled internally as an error - * but can be recovered by manual effort. - * @def BOOTENV_WPDD_STRING_DIFFERS - * @brief The PDD strings of old and new PDD differ and - * can cause update problems, because new PDD values - * are removed from the bootenv section completely. - */ -#define BOOTENV_W 20 -#define BOOTENV_WPDD_STRING_DIFFERS 21 -#define BOOTENV_WMAX 22 /* highest warning value */ - - -typedef struct bootenv *bootenv_t; - /**< A bootenv library handle. */ - -typedef struct bootenv_list *bootenv_list_t; - /**< A handle for a value list. */ - -typedef int(*pdd_func_t)(bootenv_t, bootenv_t, bootenv_t*, - int*, char*, size_t); - - -/** - * @brief Get a new handle. - * @return 0 - * @return or error - * */ -int bootenv_create(bootenv_t *env); - -/** - * @brief Cleanup structure. - * @param env Bootenv structure which shall be destroyed. - * @return 0 - * @return or error - */ -int bootenv_destroy(bootenv_t *env); - -/** - * @brief Copy a bootenv handle. - * @param in The input bootenv. - * @param out The copied output bootenv. Discards old data. - * @return 0 - * @return or error - */ -int bootenv_copy_bootenv(bootenv_t in, bootenv_t *out); - -/** - * @brief Looks for a value inside the bootenv data. - * @param env Handle to a bootenv structure. - * @param key The key. - * @return NULL key not found - * @return !NULL ptr to value - */ -int bootenv_get(bootenv_t env, const char *key, const char **value); - - -/** - * @brief Looks for a value inside the bootenv data and converts it to num. - * @param env Handle to a bootenv structure. - * @param key The key. - * @param value A pointer to the resulting numerical value - * @return NULL key not found - * @return !NULL ptr to value - */ -int bootenv_get_num(bootenv_t env, const char *key, uint32_t *value); - -/** - * @brief Set a bootenv value by key. - * @param env Handle to a bootenv structure. - * @param key Key. - * @param value Value to set. - * @return 0 - * @return or error - */ -int bootenv_set(bootenv_t env, const char *key, const char *value); - -/** - * @brief Remove the given key (and its value) from a bootenv structure. - * @param env Handle to a bootenv structure. - * @param key Key. - * @return 0 - * @return or error - */ -int bootenv_unset(bootenv_t env, const char *key); - - -/** - * @brief Get a vector of all keys which are currently set - * within a bootenv handle. - * @param env Handle to a bootenv structure. - * @param size The size of the allocated array structure. - * @param sort Flag, if set the vector is sorted ascending. - * @return NULL on error. - * @return !NULL a pointer to the first element the allocated vector. - * @warning Free the allocate memory yourself! - */ -int bootenv_get_key_vector(bootenv_t env, size_t *size, int sort, - const char ***vector); - -/** - * @brief Calculate the size in bytes which are necessary to write the - * current bootenv section in a *binary file. - * @param env bootenv handle. - * @param size The size in bytes of the bootenv handle. - * @return 0 - * @return or ERROR. - */ -int bootenv_size(bootenv_t env, size_t *size); - -/** - * @brief Read a binary bootenv file. - * @param fp File pointer to input stream. - * @param env bootenv handle. - * @param size maximum data size. - * @return 0 - * @return or ERROR. - */ -int bootenv_read(FILE* fp, bootenv_t env, size_t size); - -/** - * @param ret_crc return value of crc of read data - */ -int bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t *ret_crc); - -/** - * @brief Read bootenv data from an text/ascii file. - * @param fp File pointer to ascii PDD file. - * @param env bootenv handle - * @return 0 - * @return or ERROR. - */ -int bootenv_read_txt(FILE* fp, bootenv_t env); - -/** - * @brief Write a bootenv structure to the given location (binary). - * @param fp Filepointer to binary file. - * @param env Bootenv structure which shall be written. - * @return 0 - * @return or error - */ -int bootenv_write(FILE* fp, bootenv_t env); - -/** - * @param ret_crc return value of crc of read data - */ -int bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc); - -/** - * @brief Write a bootenv structure to the given location (text). - * @param fp Filepointer to text file. - * @param env Bootenv structure which shall be written. - * @return 0 - * @return or error - */ -int bootenv_write_txt(FILE* fp, bootenv_t env); - -/** - * @brief Compare bootenvs using memcmp(). - * @param first First bootenv. - * @param second Second bootenv. - * @return 0 if bootenvs are equal - * @return < 0 if error - * @return > 0 if unequal - */ -int bootenv_compare(bootenv_t first, bootenv_t second); - -/** - * @brief Prototype for a PDD handling funtion - */ - -/** - * @brief The PDD keep operation. - * @param env_old The old bootenv structure. - * @param env_new The new bootenv structure. - * @param env_res The result of PDD keep. - * @param warnings A flag which marks any warnings. - * @return 0 - * @return or error - * @note For a complete documentation about the algorithm confer the - * PDD documentation. - */ -int bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new, - bootenv_t *env_res, int *warnings, - char *err_buf, size_t err_buf_size); - - -/** - * @brief The PDD merge operation. - * @param env_old The old bootenv structure. - * @param env_new The new bootenv structure. - * @param env_res The result of merge-pdd. - * @param warnings A flag which marks any warnings. - * @return 0 - * @return or error - * @note For a complete documentation about the algorithm confer the - * PDD documentation. - */ -int bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new, - bootenv_t *env_res, int *warnings, - char *err_buf, size_t err_buf_size); - -/** - * @brief The PDD overwrite operation. - * @param env_old The old bootenv structure. - * @param env_new The new bootenv structure. - * @param env_res The result of overwrite-pdd. - * @param warnings A flag which marks any warnings. - * @return 0 - * @return or error - * @note For a complete documentation about the algorithm confer the - * PDD documentation. - */ -int bootenv_pdd_overwrite(bootenv_t env_new, - bootenv_t env_old, bootenv_t *env_res, int *warnings, - char *err_buf, size_t err_buf_size); - -/** - * @brief Dump a bootenv structure to stdout. (Debug) - * @param env Handle to a bootenv structure. - * @return 0 - * @return or error - */ -int bootenv_dump(bootenv_t env); - -/** - * @brief Validate a bootenv structure. - * @param env Handle to a bootenv structure. - * @return 0 - * @return or error - */ -int bootenv_valid(bootenv_t env); - -/** - * @brief Create a new bootenv list structure. - * @return NULL on error - * @return or a new list handle. - * @note This structure is used to store values in a list. - * A useful addition when handling PDD strings. - */ -int bootenv_list_create(bootenv_list_t *list); - -/** - * @brief Destroy a bootenv list structure - * @param list Handle to a bootenv list structure. - * @return 0 - * @return or error - */ -int bootenv_list_destroy(bootenv_list_t *list); - -/** - * @brief Import a list from a comma seperated string - * @param list Handle to a bootenv list structure. - * @param str Comma seperated string list. - * @return 0 - * @return or error - */ -int bootenv_list_import(bootenv_list_t list, const char *str); - -/** - * @brief Export a list to a string of comma seperated values. - * @param list Handle to a bootenv list structure. - * @return NULL one error - * @return or pointer to a newly allocated string. - * @warning Free the allocated memory by yourself! - */ -int bootenv_list_export(bootenv_list_t list, char **string); - -/** - * @brief Add an item to the list. - * @param list A handle of a list structure. - * @param item An item. - * @return 0 - * @return or error - */ -int bootenv_list_add(bootenv_list_t list, const char *item); - -/** - * @brief Remove an item from the list. - * @param list A handle of a list structure. - * @param item An item. - * @return 0 - * @return or error - */ -int bootenv_list_remove(bootenv_list_t list, const char *item); - -/** - * @brief Check if a given item is in a given list. - * @param list A handle of a list structure. - * @param item An item. - * @return 1 Item is in list. - * @return 0 Item is not in list. - */ -int bootenv_list_is_in(bootenv_list_t list, const char *item); - - -/** - * @brief Convert a list into a vector of all values inside the list. - * @param list Handle to a bootenv structure. - * @param size The size of the allocated vector structure. - * @return 0 - * @return or error - * @warning Free the allocate memory yourself! - */ -int bootenv_list_to_vector(bootenv_list_t list, size_t *size, - const char ***vector); - -/** - * @brief Convert a list into a vector of all values inside the list. - * @param list Handle to a bootenv structure. - * @param size The size of the allocated vector structure. - * @return 0 - * @return or error - * @warning Free the allocate memory yourself! - */ -int bootenv_list_to_num_vector(bootenv_list_t list, size_t *size, - uint32_t **vector); - -#ifdef __cplusplus -} -#endif -#endif /*__BOOTENV_H__ */ diff --git a/ubi-utils/sort-me-out/config.h b/ubi-utils/sort-me-out/config.h deleted file mode 100644 index 55e60f3..0000000 --- a/ubi-utils/sort-me-out/config.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __CONFIG_H__ -#define __CONFIG_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Frank Haverkamp - */ - -#define PACKAGE_BUGREPORT \ - "haver@vnet.ibm.com, dedekind@linutronix.de, or tglx@linutronix.de" - -#define ubi_unused __attribute__((unused)) - -#endif diff --git a/ubi-utils/sort-me-out/crc32.c b/ubi-utils/sort-me-out/crc32.c deleted file mode 100644 index 666e217..0000000 --- a/ubi-utils/sort-me-out/crc32.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Thomas Gleixner - */ - -/* - * CRC32 functions - * - * Can be compiled as seperate object, but is included into the ipl source - * so gcc can inline the functions. We optimize for size so the omission of - * the function frame is helpful. - * - */ - -#include <stdint.h> -#include <crc32.h> - -/* CRC polynomial */ -#define CRC_POLY 0xEDB88320 - -/** - * init_crc32_table - Initialize crc table - * - * @table: pointer to the CRC table which must be initialized - * - * Create CRC32 table for given polynomial. The table is created with - * the lowest order term in the highest order bit. So the x^32 term - * has to implied in the crc calculation function. - */ -void init_crc32_table(uint32_t *table) -{ - uint32_t crc; - int i, j; - - for (i = 0; i < 256; i++) { - crc = i; - for (j = 8; j > 0; j--) { - if (crc & 1) - crc = (crc >> 1) ^ CRC_POLY; - else - crc >>= 1; - } - table[i] = crc; - } -} - -/** - * clc_crc32 - Calculate CRC32 over a buffer - * - * @table: pointer to the CRC table - * @crc: initial crc value - * @buf: pointer to the buffer - * @len: number of bytes to calc - * - * Returns the updated crc value. - * - * The algorithm resembles a hardware shift register, but calculates 8 - * bit at once. - */ -uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, - int len) -{ - const unsigned char *p = buf; - - while(--len >= 0) - crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8); - return crc; -} diff --git a/ubi-utils/sort-me-out/crc32.h b/ubi-utils/sort-me-out/crc32.h deleted file mode 100644 index 31362b0..0000000 --- a/ubi-utils/sort-me-out/crc32.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __CRC32_H__ -#define __CRC32_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Author: Thomas Gleixner - * - * CRC32 functions - * - * Can be compiled as seperate object, but is included into the ipl source - * so gcc can inline the functions. We optimize for size so the omission of - * the function frame is helpful. - * - */ -#include <stdint.h> - -void init_crc32_table(uint32_t *table); -uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len); - -#endif /* __CRC32_H__ */ diff --git a/ubi-utils/sort-me-out/eb_chain.c b/ubi-utils/sort-me-out/eb_chain.c deleted file mode 100644 index a018ae6..0000000 --- a/ubi-utils/sort-me-out/eb_chain.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006, 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Author: Drake Dowsett, dowsett@de.ibm.com - * Contact: Andreas Arnez, arnez@de.ibm.com - */ - -/* see eb_chain.h */ - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include "unubi_analyze.h" -#include "crc32.h" - -#define COPY(dst, src) \ - do { \ - dst = malloc(sizeof(*dst)); \ - if (dst == NULL) \ - return -ENOMEM; \ - memcpy(dst, src, sizeof(*dst)); \ - } while (0) - - -/** - * inserts an eb_info into the chain starting at head, then searching - * linearly for the correct position; - * new should contain valid vid and ec headers and the data_crc should - * already have been checked before insertion, otherwise the chain - * could be have un an undesired manner; - * returns -ENOMEM if alloc fails, otherwise SHOULD always return 0, - * if not, the code reached the last line and returned -EAGAIN, - * meaning there is a bug or a case not being handled here; - **/ -int -eb_chain_insert(struct eb_info **head, struct eb_info *new) -{ - uint32_t vol, num, ver; - uint32_t new_vol, new_num, new_ver; - struct eb_info *prev, *cur, *hist, *ins; - struct eb_info **prev_ptr; - - if ((head == NULL) || (new == NULL)) - return 0; - - if (*head == NULL) { - COPY(*head, new); - (*head)->next = NULL; - return 0; - } - - new_vol = __be32_to_cpu(new->vid.vol_id); - new_num = __be32_to_cpu(new->vid.lnum); - new_ver = __be32_to_cpu(new->vid.leb_ver); - - /** TRAVERSE HORIZONTALY **/ - - cur = *head; - prev = NULL; - - /* traverse until vol_id/lnum align */ - vol = __be32_to_cpu(cur->vid.vol_id); - num = __be32_to_cpu(cur->vid.lnum); - while ((new_vol > vol) || ((new_vol == vol) && (new_num > num))) { - /* insert new at end of chain */ - if (cur->next == NULL) { - COPY(ins, new); - ins->next = NULL; - cur->next = ins; - return 0; - } - - prev = cur; - cur = cur->next; - vol = __be32_to_cpu(cur->vid.vol_id); - num = __be32_to_cpu(cur->vid.lnum); - } - - if (prev == NULL) - prev_ptr = head; - else - prev_ptr = &(prev->next); - - /* insert new into the middle of chain */ - if ((new_vol != vol) || (new_num != num)) { - COPY(ins, new); - ins->next = cur; - *prev_ptr = ins; - return 0; - } - - /** TRAVERSE VERTICALY **/ - - hist = cur; - prev = NULL; - - /* traverse until versions align */ - ver = __be32_to_cpu(cur->vid.leb_ver); - while (new_ver < ver) { - /* insert new at bottom of history */ - if (hist->older == NULL) { - COPY(ins, new); - ins->next = NULL; - ins->older = NULL; - hist->older = ins; - return 0; - } - - prev = hist; - hist = hist->older; - ver = __be32_to_cpu(hist->vid.leb_ver); - } - - if (prev == NULL) { - /* replace active version */ - COPY(ins, new); - ins->next = hist->next; - *prev_ptr = ins; - - /* place cur in vertical histroy */ - ins->older = hist; - hist->next = NULL; - return 0; - } - - /* insert between versions, beneath active version */ - COPY(ins, new); - ins->next = NULL; - ins->older = prev->older; - prev->older = ins; - return 0; -} - - -/** - * sets the pointer at pos to the position of the first entry in the chain - * with of vol_id and, if given, with the same lnum as *lnum; - * if there is no entry in the chain, then *pos is NULL on return; - * always returns 0; - **/ -int -eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum, - struct eb_info **pos) -{ - uint32_t vol, num; - struct eb_info *cur; - - if ((head == NULL) || (*head == NULL) || (pos == NULL)) - return 0; - - *pos = NULL; - - cur = *head; - while (cur != NULL) { - vol = __be32_to_cpu(cur->vid.vol_id); - num = __be32_to_cpu(cur->vid.lnum); - - if ((vol_id == vol) && ((lnum == NULL) || (*lnum == num))) { - *pos = cur; - return 0; - } - - cur = cur->next; - } - - return 0; -} - - -/** - * prints to stream, the vol_id, lnum and leb_ver for each entry in the - * chain, starting at head; - * this is intended for debuging purposes; - * always returns 0; - * - * FIXME I do not like the double list traversion ... - **/ -int -eb_chain_print(FILE* stream, struct eb_info *head) -{ - struct eb_info *cur; - - if (stream == NULL) - stream = stdout; - - if (head == NULL) { - fprintf(stream, "EMPTY\n"); - return 0; - } - /* 012345678012345678012345678012301230123 0123 01234567 0123457 01234567*/ - fprintf(stream, "VOL_ID LNUM LEB_VER EC VID DAT PBLK PADDR DSIZE EC\n"); - cur = head; - while (cur != NULL) { - struct eb_info *hist; - - fprintf(stream, "%08x %-8u %08x %-4s%-4s", - __be32_to_cpu(cur->vid.vol_id), - __be32_to_cpu(cur->vid.lnum), - __be32_to_cpu(cur->vid.leb_ver), - cur->ec_crc_ok ? "ok":"bad", - cur->vid_crc_ok ? "ok":"bad"); - if (cur->vid.vol_type == UBI_VID_STATIC) - fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"bad"); - else fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"ign"); - fprintf(stream, " %-4d %08x %-8u %-8llu\n", cur->phys_block, - cur->phys_addr, __be32_to_cpu(cur->vid.data_size), - __be64_to_cpu(cur->ec.ec)); - - hist = cur->older; - while (hist != NULL) { - fprintf(stream, "%08x %-8u %08x %-4s%-4s", - __be32_to_cpu(hist->vid.vol_id), - __be32_to_cpu(hist->vid.lnum), - __be32_to_cpu(hist->vid.leb_ver), - hist->ec_crc_ok ? "ok":"bad", - hist->vid_crc_ok ? "ok":"bad"); - if (hist->vid.vol_type == UBI_VID_STATIC) - fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"bad"); - else fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"ign"); - fprintf(stream, " %-4d %08x %-8u %-8llu (*)\n", - hist->phys_block, hist->phys_addr, - __be32_to_cpu(hist->vid.data_size), - __be64_to_cpu(hist->ec.ec)); - - hist = hist->older; - } - cur = cur->next; - } - - return 0; -} - - -/** - * frees the memory of the entire chain, starting at head; - * head will be NULL on return; - * always returns 0; - **/ -int -eb_chain_destroy(struct eb_info **head) -{ - if (head == NULL) - return 0; - - while (*head != NULL) { - struct eb_info *cur; - struct eb_info *hist; - - cur = *head; - *head = (*head)->next; - - hist = cur->older; - while (hist != NULL) { - struct eb_info *temp; - - temp = hist; - hist = hist->older; - free(temp); - } - free(cur); - } - return 0; -} - diff --git a/ubi-utils/sort-me-out/ecclayouts.h b/ubi-utils/sort-me-out/ecclayouts.h deleted file mode 100644 index a1c7823..0000000 --- a/ubi-utils/sort-me-out/ecclayouts.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __ECCLAYOUTS_H__ -#define __ECCLAYOUTS_H__ -/* - * Copyright (c) International Business Machines Corp., 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdint.h> -#include <mtd/mtd-abi.h> - -/* Define default oob placement schemes for large and small page devices */ -static struct nand_ecclayout mtd_nand_oob_16 = { - .eccbytes = 6, - .eccpos = { 0, 1, 2, 3, 6, 7 }, - .oobfree = {{ .offset = 8, .length = 8 }} -}; - -static struct nand_ecclayout mtd_nand_oob_64 = { - .eccbytes = 24, - .eccpos = { 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63 }, - .oobfree = {{ .offset = 2, .length = 38 }} -}; - -/* Define IBM oob placement schemes */ -static struct nand_ecclayout ibm_nand_oob_16 = { - .eccbytes = 6, - .eccpos = { 9, 10, 11, 13, 14, 15 }, - .oobfree = {{ .offset = 8, .length = 8 }} -}; - -static struct nand_ecclayout ibm_nand_oob_64 = { - .eccbytes = 24, - .eccpos = { 33, 34, 35, 37, 38, 39, 41, 42, - 43, 45, 46, 47, 49, 50, 51, 53, - 54, 55, 57, 58, 59, 61, 62, 63 }, - .oobfree = {{ .offset = 2, .length = 30 }} -}; - -struct oob_placement { - const char *name; - struct nand_ecclayout *nand_oob[2]; -}; - -static struct oob_placement oob_placement[] = { - { .name = "IBM", - .nand_oob = { &ibm_nand_oob_16, &ibm_nand_oob_64 }}, - { .name = "MTD", - .nand_oob = { &mtd_nand_oob_16, &mtd_nand_oob_64 }}, -}; - -#endif diff --git a/ubi-utils/sort-me-out/error.c b/ubi-utils/sort-me-out/error.c deleted file mode 100644 index 4aaedad..0000000 --- a/ubi-utils/sort-me-out/error.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdio.h> -#include <stdarg.h> -#include <syslog.h> -#include <stdlib.h> -#include <sys/errno.h> -#include <string.h> -#include "error.h" - -#define MAXLINE 4096 -#define MAXWIDTH 80 - -static FILE *logfp = NULL; - -static void err_doit(int, int, const char *, va_list); - -int -read_procfile(FILE *fp_out, const char *procfile) -{ - FILE *fp; - - if (!fp_out) - return -ENXIO; - - fp = fopen(procfile, "r"); - if (!fp) - return -ENOENT; - - while(!feof(fp)) { - int c = fgetc(fp); - - if (c == EOF) - return 0; - - if (putc(c, fp_out) == EOF) - return -EIO; - - if (ferror(fp)) - return -EIO; - } - return fclose(fp); -} - -void -error_initlog(const char *logfile) -{ - if (!logfile) - return; - - logfp = fopen(logfile, "a+"); - read_procfile(logfp, "/proc/cpuinfo"); -} - -void -info_msg(const char *fmt, ...) -{ - FILE* fpout; - char buf[MAXLINE + 1]; - va_list ap; - int n; - - fpout = stdout; - - va_start(ap, fmt); - vsnprintf(buf, MAXLINE, fmt, ap); - n = strlen(buf); - strcat(buf, "\n"); - - fputs(buf, fpout); - fflush(fpout); - if (fpout != stdout) - fclose(fpout); - - va_end(ap); - return; -} - -void -__err_ret(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(1, LOG_INFO, fmt, ap); - va_end(ap); - return; -} - -void -__err_sys(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(1, LOG_ERR, fmt, ap); - va_end(ap); - exit(EXIT_FAILURE); -} - - -void -__err_msg(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(0, LOG_INFO, fmt, ap); - va_end(ap); - - return; -} - -void -__err_quit(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(0, LOG_ERR, fmt, ap); - va_end(ap); - exit(EXIT_FAILURE); -} - -void -__err_dump(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(1, LOG_ERR, fmt, ap); - va_end(ap); - abort(); /* dump core and terminate */ - exit(EXIT_FAILURE); /* shouldn't get here */ -} - -/** - * If a logfile is used we must not print on stderr and stdout - * anymore. Since pfilfash might be used in a server context, it is - * even dangerous to write to those descriptors. - */ -static void -err_doit(int errnoflag, int level __attribute__((unused)), - const char *fmt, va_list ap) -{ - FILE* fpout; - int errno_save, n; - char buf[MAXLINE + 1]; - fpout = stderr; - - errno_save = errno; /* value caller might want printed */ - - vsnprintf(buf, MAXLINE, fmt, ap); /* safe */ - - n = strlen(buf); - - if (errnoflag) - snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save)); - strcat(buf, "\n"); - - if (logfp) { - fputs(buf, logfp); - fflush(logfp); - return; /* exit when logging completes */ - } - - if (fpout == stderr) { - /* perform line wrap when outputting to stderr */ - int word_len, post_len, chars; - char *buf_ptr; - const char *frmt = "%*s%n %n"; - - chars = 0; - buf_ptr = buf; - while (sscanf(buf_ptr, frmt, &word_len, &post_len) != EOF) { - int i; - char word[word_len + 1]; - char post[post_len + 1]; - - strncpy(word, buf_ptr, word_len); - word[word_len] = '\0'; - buf_ptr += word_len; - post_len -= word_len; - - if (chars + word_len > MAXWIDTH) { - fputc('\n', fpout); - chars = 0; - } - fputs(word, fpout); - chars += word_len; - - if (post_len > 0) { - strncpy(post, buf_ptr, post_len); - post[post_len] = '\0'; - buf_ptr += post_len; - } - for (i = 0; i < post_len; i++) { - int inc = 1, chars_new; - - if (post[i] == '\t') - inc = 8; - if (post[i] == '\n') { - inc = 0; - chars_new = 0; - } else - chars_new = chars + inc; - - if (chars_new > MAXWIDTH) { - fputc('\n', fpout); - chars_new = inc; - } - fputc(post[i], fpout); - chars = chars_new; - } - } - } - else - fputs(buf, fpout); - fflush(fpout); - if (fpout != stderr) - fclose(fpout); - - return; -} diff --git a/ubi-utils/sort-me-out/error.h b/ubi-utils/sort-me-out/error.h deleted file mode 100644 index 05d8078..0000000 --- a/ubi-utils/sort-me-out/error.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef __ERROR_H__ -#define __ERROR_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdio.h> - -void error_initlog(const char *logfile); -int read_procfile(FILE *fp_out, const char *procfile); - -void __err_ret(const char *fmt, ...); -void __err_sys(const char *fmt, ...); -void __err_msg(const char *fmt, ...); -void __err_quit(const char *fmt, ...); -void __err_dump(const char *fmt, ...); - -void info_msg(const char *fmt, ...); - -#ifdef DEBUG -#define __loc_msg(str) do { \ - __err_msg("[%s. FILE: %s FUNC: %s LINE: %d]\n", \ - str, __FILE__, __FUNCTION__, __LINE__); \ -} while (0) -#else -#define __loc_msg(str) -#endif - - -#define err_dump(fmt, ...) do { \ - __loc_msg("ErrDump"); \ - __err_dump(fmt, ##__VA_ARGS__); \ -} while (0) - -#define err_quit(fmt, ...) do { \ - __loc_msg("ErrQuit"); \ - __err_quit(fmt, ##__VA_ARGS__); \ -} while (0) - - -#define err_ret(fmt, ...) do { \ - __loc_msg("ErrRet"); \ - __err_ret(fmt, ##__VA_ARGS__); \ -} while (0) - -#define err_sys(fmt, ...) do { \ - __loc_msg("ErrSys"); \ - __err_sys(fmt, ##__VA_ARGS__); \ -} while (0) - -#define err_msg(fmt, ...) do { \ - __loc_msg("ErrMsg"); \ - __err_msg(fmt, ##__VA_ARGS__); \ -} while (0) - -#define log_msg(fmt, ...) do { \ - /* __loc_msg("LogMsg"); */ \ - __err_msg(fmt, ##__VA_ARGS__); \ -} while (0) - -#ifdef DEBUG -#define dbg_msg(fmt, ...) do { \ - __loc_msg("DbgMsg"); \ - __err_msg(fmt, ##__VA_ARGS__); \ -} while (0) -#else -#define dbg_msg(fmt, ...) do {} while (0) -#endif - -#endif /* __ERROR_H__ */ diff --git a/ubi-utils/sort-me-out/example_ubi.h b/ubi-utils/sort-me-out/example_ubi.h deleted file mode 100644 index 23c7b54..0000000 --- a/ubi-utils/sort-me-out/example_ubi.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __EXAMPLE_UBI_H__ -#define __EXAMPLE_UBI_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * Defaults for our cards. - */ -#define EXAMPLE_UBI_DEVICE 0 -#define EXAMPLE_BOOTENV_VOL_ID_1 4 -#define EXAMPLE_BOOTENV_VOL_ID_2 5 - -#endif /* __EXAMPLE_UBI_H__ */ diff --git a/ubi-utils/sort-me-out/f128_nand_sample.cfg b/ubi-utils/sort-me-out/f128_nand_sample.cfg deleted file mode 100644 index bb62600..0000000 --- a/ubi-utils/sort-me-out/f128_nand_sample.cfg +++ /dev/null @@ -1,38 +0,0 @@ -[targets] -complete=ipl,spl,bootenv,kernel,rootfs -bootcode=spl,bootenv - -# Build sections -[ipl] -image=ipl.bin -raw_starts=0x00000000 -raw_total_size=128kiB - -[spl] -image=u-boot.bin -ubi_ids=2,3 -ubi_size=2MiB -ubi_type=static -ubi_names=spl_0,spl_1 - -[bootenv] -bootenv_file=bootenv_complete.txt -ubi_ids=4,5 -ubi_size=128kiB -ubi_type=static -ubi_names=bootenv_0,bootenv_1 - -[kernel] -image=vmlinux.bin -ubi_ids=6,7 -ubi_size=6MiB -ubi_type=static -ubi_names=kernel_0,kernel_1 - -[rootfs] -image=rootfs.bin -ubi_ids=8,9 -ubi_alignment=2kiB -ubi_size=16MiB -ubi_type=dynamic -ubi_names=rootfs_0,rootfs_1 diff --git a/ubi-utils/sort-me-out/f64_nor_sample.cfg b/ubi-utils/sort-me-out/f64_nor_sample.cfg deleted file mode 100644 index 889d4c2..0000000 --- a/ubi-utils/sort-me-out/f64_nor_sample.cfg +++ /dev/null @@ -1,39 +0,0 @@ -[targets] -complete=ipl,spl,bootenv,kernel,rootfs -bootcode=spl,bootenv -rootfs=rootfs - -# Build sections -[ipl] -image=ipl.bin -raw_starts=0x02FE0000, 0x03FE0000 -raw_total_size=128kiB - -[spl] -image=u-boot.bin -ubi_ids=2,3 -ubi_size=2MiB -ubi_type=static -ubi_names=spl_0,spl_1 - -[bootenv] -bootenv_file=bootenv_complete.txt -ubi_ids=4,5 -ubi_size=128kiB -ubi_type=static -ubi_names=bootenv_0,bootenv_1 - -[kernel] -image=vmlinux.bin -ubi_ids=6,7 -ubi_size=6MiB -ubi_type=static -ubi_names=kernel_0,kernel_1 - -[rootfs] -image=rootfs.bin -ubi_ids=8,9 -ubi_alignment=2kiB -ubi_size=16128kiB -ubi_type=dynamic -ubi_names=rootfs_0,rootfs_1 diff --git a/ubi-utils/sort-me-out/hashmap.c b/ubi-utils/sort-me-out/hashmap.c deleted file mode 100644 index 3511d56..0000000 --- a/ubi-utils/sort-me-out/hashmap.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -#include <errno.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include "error.h" -#include "hashmap.h" -#define DEFAULT_BUCKETS 4096 - -#if 0 -#define INFO_MSG(fmt...) do { \ - info_msg(fmt); \ -} while (0) -#else -#define INFO_MSG(fmt...) -#endif - -struct hashentry { - char* key; /* key '0' term. str */ - char* value; /* payload '0' term. str */ - - hashentry_t next; -}; - -struct hashmap { - size_t entries; /* current #entries */ - size_t maxsize; /* no. of hash buckets */ - hashentry_t* data; /* array of buckets */ -}; - -static int -is_empty(hashentry_t l) -{ - return l == NULL ? 1 : 0; -} - -hashmap_t -hashmap_new(void) -{ - hashmap_t res; - res = (hashmap_t) calloc(1, sizeof(struct hashmap)); - - if (res == NULL) - return NULL; - - res->maxsize = DEFAULT_BUCKETS; - res->entries = 0; - - res->data = (hashentry_t*) - calloc(1, res->maxsize * sizeof(struct hashentry)); - - if (res->data == NULL) - return NULL; - - return res; -} - -static hashentry_t -new_entry(const char* key, const char* value) -{ - hashentry_t res; - - res = (hashentry_t) calloc(1, sizeof(struct hashentry)); - - if (res == NULL) - return NULL; - - /* allocate key and value and copy them */ - res->key = strdup(key); - if (res->key == NULL) { - free(res); - return NULL; - } - - res->value = strdup(value); - if (res->value == NULL) { - free(res->key); - free(res); - return NULL; - } - - res->next = NULL; - - return res; -} - -static hashentry_t -free_entry(hashentry_t e) -{ - if (!is_empty(e)) { - if(e->key != NULL) { - free(e->key); - } - if(e->value != NULL) - free(e->value); - free(e); - } - - return NULL; -} - -static hashentry_t -remove_entry(hashentry_t l, const char* key, size_t* entries) -{ - hashentry_t lnext; - if (is_empty(l)) - return NULL; - - if(strcmp(l->key,key) == 0) { - lnext = l->next; - l = free_entry(l); - (*entries)--; - return lnext; - } - - l->next = remove_entry(l->next, key, entries); - - return l; -} - -static hashentry_t -insert_entry(hashentry_t l, hashentry_t e, size_t* entries) -{ - if (is_empty(l)) { - (*entries)++; - return e; - } - - /* check for update */ - if (strcmp(l->key, e->key) == 0) { - e->next = l->next; - l = free_entry(l); - return e; - } - - l->next = insert_entry(l->next, e, entries); - return l; -} - -static hashentry_t -remove_all(hashentry_t l, size_t* entries) -{ - hashentry_t lnext; - if (is_empty(l)) - return NULL; - - lnext = l->next; - free_entry(l); - (*entries)--; - - return remove_all(lnext, entries); -} - -static const char* -value_lookup(hashentry_t l, const char* key) -{ - if (is_empty(l)) - return NULL; - - if (strcmp(l->key, key) == 0) - return l->value; - - return value_lookup(l->next, key); -} - -static void -print_all(hashentry_t l) -{ - if (is_empty(l)) { - printf("\n"); - return; - } - - printf("%s=%s", l->key, l->value); - if (!is_empty(l->next)) { - printf(","); - } - - print_all(l->next); -} - -static void -keys_to_array(hashentry_t l, const char** a, size_t* i) -{ - if (is_empty(l)) - return; - - a[*i] = l->key; - (*i)++; - - keys_to_array(l->next, a, i); -} - -uint32_t -hash_str(const char* str, uint32_t mapsize) -{ - uint32_t hash = 0; - uint32_t x = 0; - uint32_t i = 0; - size_t len = strlen(str); - - for(i = 0; i < len; str++, i++) { - hash = (hash << 4) + (*str); - if((x = hash & 0xF0000000L) != 0) { - hash ^= (x >> 24); - hash &= ~x; - } - } - - return (hash & 0x7FFFFFFF) % mapsize; -} - - -int -hashmap_is_empty(hashmap_t map) -{ - if (map == NULL) - return -EINVAL; - - return map->entries > 0 ? 1 : 0; -} - -const char* -hashmap_lookup(hashmap_t map, const char* key) -{ - uint32_t i; - - if ((map == NULL) || (key == NULL)) - return NULL; - - i = hash_str(key, map->maxsize); - - return value_lookup(map->data[i], key); -} - -int -hashmap_add(hashmap_t map, const char* key, const char* value) -{ - uint32_t i; - hashentry_t entry; - - if ((map == NULL) || (key == NULL) || (value == NULL)) - return -EINVAL; - - i = hash_str(key, map->maxsize); - entry = new_entry(key, value); - if (entry == NULL) - return -ENOMEM; - - map->data[i] = insert_entry(map->data[i], - entry, &map->entries); - - INFO_MSG("HASH_ADD: chain[%d] key:%s val:%s",i, key, value); - return 0; -} - -int -hashmap_remove(hashmap_t map, const char* key) -{ - uint32_t i; - - if ((map == NULL) || (key == NULL)) - return -EINVAL; - - i = hash_str(key, map->maxsize); - map->data[i] = remove_entry(map->data[i], key, &map->entries); - - return 0; -} - -size_t -hashmap_size(hashmap_t map) -{ - if (map != NULL) - return map->entries; - else - return 0; -} - -int -hashmap_free(hashmap_t map) -{ - size_t i; - - if (map == NULL) - return -EINVAL; - - /* "children" first */ - for(i = 0; i < map->maxsize; i++) { - map->data[i] = remove_all(map->data[i], &map->entries); - } - free(map->data); - free(map); - - return 0; -} - -int -hashmap_dump(hashmap_t map) -{ - size_t i; - if (map == NULL) - return -EINVAL; - - for(i = 0; i < map->maxsize; i++) { - if (map->data[i] != NULL) { - printf("[%zd]: ", i); - print_all(map->data[i]); - } - } - - return 0; -} - -static const char** -sort_key_vector(const char** a, size_t size) -{ - /* uses bubblesort */ - size_t i, j; - const char* tmp; - - if (size <= 0) - return a; - - for (i = size - 1; i > 0; i--) { - for (j = 0; j < i; j++) { - if (strcmp(a[j], a[j+1]) > 0) { - tmp = a[j]; - a[j] = a[j+1]; - a[j+1] = tmp; - } - } - } - return a; -} - -const char** -hashmap_get_key_vector(hashmap_t map, size_t* size, int sort) -{ - const char** res; - size_t i, j; - *size = map->entries; - - res = (const char**) malloc(*size * sizeof(char*)); - if (res == NULL) - return NULL; - - j = 0; - for(i=0; i < map->maxsize; i++) { - keys_to_array(map->data[i], res, &j); - } - - if (sort) - res = sort_key_vector(res, *size); - - return res; -} - -int -hashmap_key_is_in_vector(const char** vec, size_t size, const char* key) -{ - size_t i; - for (i = 0; i < size; i++) { - if (strcmp(vec[i], key) == 0) /* found */ - return 1; - } - - return 0; -} - -const char** -hashmap_get_update_key_vector(const char** vec1, size_t vec1_size, - const char** vec2, size_t vec2_size, size_t* res_size) -{ - const char** res; - size_t i, j; - - *res_size = vec2_size; - - res = (const char**) malloc(*res_size * sizeof(char*)); - if (res == NULL) - return NULL; - - /* get all keys from vec2 which are not set in vec1 */ - j = 0; - for (i = 0; i < vec2_size; i++) { - if (!hashmap_key_is_in_vector(vec1, vec1_size, vec2[i])) - res[j++] = vec2[i]; - } - - *res_size = j; - return res; -} diff --git a/ubi-utils/sort-me-out/hashmap.h b/ubi-utils/sort-me-out/hashmap.h deleted file mode 100644 index 1b13e95..0000000 --- a/ubi-utils/sort-me-out/hashmap.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __HASHMAP_H__ -#define __HASHMAP_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -#include <stdlib.h> -#include <stdint.h> - -typedef struct hashentry *hashentry_t; -typedef struct hashmap *hashmap_t; - -hashmap_t hashmap_new(void); -int hashmap_free(hashmap_t map); - -int hashmap_add(hashmap_t map, const char* key, const char* value); -int hashmap_update(hashmap_t map, const char* key, const char* value); -int hashmap_remove(hashmap_t map, const char* key); -const char* hashmap_lookup(hashmap_t map, const char* key); - -const char** hashmap_get_key_vector(hashmap_t map, size_t* size, int sort); -int hashmap_key_is_in_vector(const char** vec, size_t size, const char* key); -const char** hashmap_get_update_key_vector(const char** vec1, size_t vec1_size, - const char** vec2, size_t vec2_size, size_t* res_size); - -int hashmap_dump(hashmap_t map); - -int hashmap_is_empty(hashmap_t map); -size_t hashmap_size(hashmap_t map); - -uint32_t hash_str(const char* str, uint32_t mapsize); - -#endif /* __HASHMAP_H__ */ diff --git a/ubi-utils/sort-me-out/inject_biterror.pl b/ubi-utils/sort-me-out/inject_biterror.pl deleted file mode 100755 index b4a862a..0000000 --- a/ubi-utils/sort-me-out/inject_biterror.pl +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/perl -w -# -# 2007 Frank Haverkamp <haver@vnet.ibm.com> -# -# Program for bit-error injection. I am sure that perl experts do it -# in 1 line. Please let me know how it is done right ;-). -# - -use strict; -use warnings; -use Getopt::Long; -use Pod::Usage; - -my $i; -my $help; -my $result; -my $offset = 0; -my $bitmask = 0x01; -my $in = "input.mif"; -my $out = "output.mif"; - -$result = GetOptions ("offset=i" => \$offset, # numeric - "bitmask=o" => \$bitmask, # numeric - "input=s" => \$in, # string - "output=s" => \$out, # string - "help|?" => \$help) or pod2usage(2); - -pod2usage(1) if $help; - -my $buf; - -open(my $in_fh, "<", $in) - or die "Cannot open file $in: $!"; -binmode $in_fh; - -open(my $out_fh, ">", $out) or - die "Cannot open file $out: $!"; -binmode $out_fh; - -$i = 0; -while (sysread($in_fh, $buf, 1)) { - - $buf = pack('C', unpack('C', $buf) ^ $bitmask) if ($i == $offset); - syswrite($out_fh, $buf, 1) or - die "Cannot write to offset $offset: $!"; - $i++; -} - -close $in_fh; -close $out_fh; - -__END__ - -=head1 NAME - -inject_biterrors.pl - -=head1 SYNOPSIS - -inject_biterror.pl [options] - -=head1 OPTIONS - -=over 8 - -=item B<--help> - -Print a brief help message and exits. - -=item B<--offset>=I<offset> - -Byte-offset where bit-error should be injected. - -=item B<--bitmask>=I<bitmask> - -Bit-mask where to inject errors in the byte. - -=item B<--input>=I<input-file> - -Input file. - -=item B<--output>=I<output-file> - -Output file. - -=back - -=head1 DESCRIPTION - -B<inject_biterrors.pl> will read the given input file and inject -biterrors at the I<offset> specified. The location of the biterrors -are defined by the I<bitmask> parameter. - -=cut diff --git a/ubi-utils/sort-me-out/jffs2_test.sh b/ubi-utils/sort-me-out/jffs2_test.sh deleted file mode 100755 index 0cc9f0c..0000000 --- a/ubi-utils/sort-me-out/jffs2_test.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/sh -# -# Testcase for JFFS2 verification. We do not want to see any -# kernel errors occuring when this is executed. -# -# -# To have a standardized output I define the following function to be -# used when a test was ok or when it failed. -# -failed () -{ - echo "FAILED" -} - -passed () -{ - echo "PASSED" -} - -# -# Print sucess message. Consider to exit with zero as return code. -# -exit_success () -{ - echo "SUCCESS" - exit 0 -} - -# -# Print failure message. Consider to exit with non zero return code. -# -exit_failure () -{ - echo "FAILED" - exit 1 -} - -echo "***********************************************************************" -echo "* jffs2 testing ... *" -echo "***********************************************************************" - -ulimit -c unlimited - -for i in `seq 5000`; do - echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... " - dd if=/dev/urandom of=test.bin bs=$i count=1; - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - - echo "Copy to different file ... " - dd if=test.bin of=new.bin bs=$i count=1; - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - - echo "Comparing files ... " - cmp test.bin new.bin - dd if=test.bin of=new.bin bs=$i count=1; - if [ $? -ne "0" ] ; then - exit_failure - fi - passed -done - -for i in `seq 5000`; do - echo "Testing $i byte (dd if=/dev/urandom of=foo bs=$i count=1) ... " - dd if=/dev/urandom of=foo bs=$i count=1; - if [ $? -ne "0" ] ; then - exit_failure - fi - passed -done - -for i in `seq 5000`; do - echo "Testing $i byte (dd if=/dev/zero of=foo bs=$i count=1) ... " - dd if=/dev/zero of=foo bs=$i count=1; - if [ $? -ne "0" ] ; then - exit_failure - fi - passed -done - -echo "***********************************************************************" -echo "* Congratulations, no errors found! *" -echo "* Have fun with your cool JFFS2 using system! *" -echo "***********************************************************************" - -exit_success diff --git a/ubi-utils/sort-me-out/libpfiflash.c b/ubi-utils/sort-me-out/libpfiflash.c deleted file mode 100644 index 7e3d3b3..0000000 --- a/ubi-utils/sort-me-out/libpfiflash.c +++ /dev/null @@ -1,1325 +0,0 @@ -/* - * Copyright International Business Machines Corp., 2006, 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Authors: Oliver Lohmann <oliloh@de.ibm.com> - * Drake Dowsett <dowsett@de.ibm.com> - * Contact: Andreas Arnez <anrez@de.ibm.com> - */ - -/* TODO Compare data before writing it. This implies that the volume - * parameters are compared first: size, alignment, name, type, ..., - * this is the same, compare the data. Volume deletion is deffered - * until the difference has been found out. - */ - -#include <stdio.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#define __USE_GNU -#include <string.h> -#include <stdlib.h> -#include <limits.h> -#include <sys/ioctl.h> - -#include <libubi.h> -#include <pfiflash.h> - -#include <mtd/ubi-user.h> /* FIXME Is this ok here? */ -#include <mtd/mtd-user.h> - -#include "pfiflash_error.h" -#include "ubimirror.h" -#include "error.h" -#include "reader.h" -#include "example_ubi.h" -#include "bootenv.h" - -/* ubi-header.h and crc32.h needed for CRC checking */ -#include <mtd/ubi-header.h> /* FIXME Is this ok here? */ -#include "crc32.h" - -#define ubi_unused __attribute__((unused)) - -#define COMPARE_BUFFER_SIZE 2048 - -#define DEFAULT_DEV_PATTERN "/dev/ubi%d" -#define DEFAULT_VOL_PATTERN "/dev/ubi%d_%d" - -static const char copyright [] ubi_unused = - "Copyright International Business Machines Corp., 2006, 2007"; - -/* simply clear buffer, then write into front of it */ -#define EBUF(fmt...) \ - snprintf(err_buf, err_buf_size, fmt); - -/* make a history of buffer and then prepend something in front */ -#define EBUF_PREPEND(fmt) \ - do { \ - int EBUF_HISTORY_LENGTH = strlen(err_buf); \ - char EBUF_HISTORY[EBUF_HISTORY_LENGTH + 1]; \ - strncpy(EBUF_HISTORY, err_buf, EBUF_HISTORY_LENGTH + 1);\ - EBUF(fmt ": %s", EBUF_HISTORY); \ - } while (0) - -/* An array of PDD function pointers indexed by the algorithm. */ -static pdd_func_t pdd_funcs[PDD_HANDLING_NUM] = - { - &bootenv_pdd_keep, - &bootenv_pdd_merge, - &bootenv_pdd_overwrite - }; - -typedef enum ubi_update_process_t { - UBI_REMOVE = 0, - UBI_WRITE, - UBI_COMPARE, -} ubi_update_process_t; - - -/** - * skip_raw_volumes - reads data from pfi to advance fp past raw block - * @pfi: fp to pfi data - * @pfi_raws: header information - * - * Error handling): - * when early EOF in pfi data - * - returns -PFIFLASH_ERR_EOF, err_buf matches text to err - * when file I/O error - * - returns -PFIFLASH_ERR_FIO, err_buf matches text to err - **/ -static int -skip_raw_volumes(FILE* pfi, list_t pfi_raws, - char* err_buf, size_t err_buf_size) -{ - int rc; - void *i; - list_t ptr; - - if (is_empty(pfi_raws)) - return 0; - - rc = 0; - foreach(i, ptr, pfi_raws) { - size_t j; - pfi_raw_t raw; - - raw = (pfi_raw_t)i; - for(j = 0; j < raw->data_size; j++) { - int c; - - c = fgetc(pfi); - if (c == EOF) - rc = -PFIFLASH_ERR_EOF; - else if (ferror(pfi)) - rc = -PFIFLASH_ERR_FIO; - - if (rc != 0) - goto err; - } - } - - err: - EBUF(PFIFLASH_ERRSTR[-rc]); - return rc; -} - - -/** - * my_ubi_mkvol - wraps the ubi_mkvol functions and impl. bootenv update hook - * @devno: UBI device number. - * @s: Current seqnum. - * @u: Information about the UBI volume from the PFI. - * - * Error handling: - * when UBI system couldn't be opened - * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err - * when UBI system couldn't create a volume - * - returns -PFIFLASH_ERR_UBI_MKVOL, err_buf matches text to err - **/ -static int -my_ubi_mkvol(int devno, int s, pfi_ubi_t u, - char *err_buf, size_t err_buf_size) -{ - int rc, type; - char path[PATH_MAX]; - libubi_t ulib; - struct ubi_mkvol_request req; - - rc = 0; - ulib = NULL; - - log_msg("[ ubimkvol id=%d, size=%d, data_size=%d, type=%d, " - "alig=%d, nlen=%d, name=%s", - u->ids[s], u->size, u->data_size, u->type, u->alignment, - strnlen(u->names[s], PFI_UBI_VOL_NAME_LEN), u->names[s]); - - ulib = libubi_open(); - if (ulib == NULL) { - rc = -PFIFLASH_ERR_UBI_OPEN; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - switch (u->type) { - case pfi_ubi_static: - type = UBI_STATIC_VOLUME; break; - case pfi_ubi_dynamic: - default: - type = UBI_DYNAMIC_VOLUME; - } - - snprintf(path, PATH_MAX, DEFAULT_DEV_PATTERN, devno); - - req.vol_id = u->ids[s]; - req.alignment = u->alignment; - req.bytes = u->size; - req.vol_type = type; - req.name = u->names[s]; - - rc = ubi_mkvol(ulib, path, &req); - if (rc != 0) { - rc = -PFIFLASH_ERR_UBI_MKVOL; - EBUF(PFIFLASH_ERRSTR[-rc], u->ids[s]); - goto err; - } - - err: - if (ulib != NULL) - libubi_close(ulib); - - return rc; -} - - -/** - * my_ubi_rmvol - a wrapper around the UBI library function ubi_rmvol - * @devno UBI device number - * @id UBI volume id to remove - * - * If the volume does not exist, the function will return success. - * - * Error handling: - * when UBI system couldn't be opened - * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err - * when UBI system couldn't update (truncate) a volume - * - returns -PFIFLASH_ERR_UBI_VOL_UPDATE, err_buf matches text to err - * when UBI system couldn't remove a volume - * - returns -PFIFLASH_ERR_UBI_RMVOL, err_buf matches text to err - **/ -static int -my_ubi_rmvol(int devno, uint32_t id, - char *err_buf, size_t err_buf_size) -{ - int rc, fd; - char path[PATH_MAX]; - libubi_t ulib; - - rc = 0; - ulib = NULL; - - log_msg("[ ubirmvol id=%d", id); - - ulib = libubi_open(); - if (ulib == NULL) { - rc = -PFIFLASH_ERR_UBI_OPEN; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); - - /* truncate whether it exist or not */ - fd = open(path, O_RDWR); - if (fd < 0) { - libubi_close(ulib); - return 0; /* not existent, return 0 */ - } - - rc = ubi_update_start(ulib, fd, 0); - close(fd); - if (rc < 0) { - rc = -PFIFLASH_ERR_UBI_VOL_UPDATE; - EBUF(PFIFLASH_ERRSTR[-rc], id); - goto err; /* if EBUSY than empty device, continue */ - } - - snprintf(path, PATH_MAX, DEFAULT_DEV_PATTERN, devno); - - rc = ubi_rmvol(ulib, path, id); - if (rc != 0) { -#ifdef DEBUG - int rc_old = rc; - dbg_msg("Remove UBI volume %d returned with error: %d " - "errno=%d", id, rc_old, errno); -#endif - - rc = -PFIFLASH_ERR_UBI_RMVOL; - EBUF(PFIFLASH_ERRSTR[-rc], id); - - /* TODO Define a ubi_rmvol return value which says - * sth like EUBI_NOSUCHDEV. In this case, a failed - * operation is acceptable. Everything else has to be - * classified as real error. But talk to Andreas Arnez - * before defining something odd... - */ - /* if ((errno == EINVAL) || (errno == ENODEV)) - return 0; */ /* currently it is EINVAL or ENODEV */ - - goto err; - } - - err: - if (ulib != NULL) - libubi_close(ulib); - - return rc; -} - - -/** - * read_bootenv_volume - reads the current bootenv data from id into be_old - * @devno UBI device number - * @id UBI volume id to remove - * @bootenv_old to hold old boot_env data - * - * Error handling: - * when UBI system couldn't be opened - * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err - * when UBI system couldn't open a volume to read - * - returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err - * when couldn't read bootenv data - * - returns -PFIFLASH_ERR_BOOTENV_READ, err_buf matches text to err - **/ -static int -read_bootenv_volume(int devno, uint32_t id, bootenv_t bootenv_old, - char *err_buf, size_t err_buf_size) -{ - int rc; - FILE* fp_in; - char path[PATH_MAX]; - libubi_t ulib; - - rc = 0; - fp_in = NULL; - ulib = NULL; - - ulib = libubi_open(); - if (ulib == NULL) { - rc = -PFIFLASH_ERR_UBI_OPEN; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); - - fp_in = fopen(path, "r"); - if (!fp_in) { - rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; - EBUF(PFIFLASH_ERRSTR[-rc], id); - goto err; - } - - log_msg("[ reading old bootenvs ..."); - - /* Save old bootenvs for reference */ - rc = bootenv_read(fp_in, bootenv_old, BOOTENV_MAXSIZE); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_READ; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - err: - if (fp_in) - fclose(fp_in); - if (ulib) - libubi_close(ulib); - - return rc; -} - - -/** - * write_bootenv_volume - writes data from PFI file int to bootenv UBI volume - * @devno UBI device number - * @id UBI volume id - * @bootend_old old PDD data from machine - * @pdd_f function to handle PDD with - * @fp_in new pdd data contained in PFI - * @fp_in_size data size of new pdd data in PFI - * @pfi_crc crc value from PFI header - * - * Error handling: - * when UBI system couldn't be opened - * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err - * when bootenv can't be created - * - returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err - * when bootenv can't be read - * - returns -PFIFLASH_ERR_BOOTENV_READ, err_buf matches text to err - * when PDD handling function returns and error - * - passes rc and err_buf data - * when CRC check fails - * - returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err - * when bootenv can't be resized - * - returns -PFIFLASH_ERR_BOOTENV_SIZE, err_buf matches text to err - * when UBI system couldn't open a volume - * - returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err - * when couldn't write bootenv data - * - returns -PFIFLASH_ERR_BOOTENV_WRITE, err_buf matches text to err - **/ -static int -write_bootenv_volume(int devno, uint32_t id, bootenv_t bootenv_old, - pdd_func_t pdd_f, FILE* fp_in, size_t fp_in_size, - uint32_t pfi_crc, - char *err_buf, size_t err_buf_size) -{ - int rc, warnings, fd_out; - uint32_t crc; - char path[PATH_MAX]; - size_t update_size; - FILE *fp_out; - bootenv_t bootenv_new, bootenv_res; - libubi_t ulib; - - rc = 0; - warnings = 0; - crc = 0; - update_size = 0; - fp_out = NULL; - bootenv_new = NULL; - bootenv_res = NULL; - ulib = NULL; - - log_msg("[ ubiupdatevol bootenv id=%d, fp_in=%p", id, fp_in); - - /* Workflow: - * 1. Apply PDD operation and get the size of the returning - * bootenv_res section. Without the correct size it wouldn't - * be possible to call UBI update vol. - * 2. Call UBI update vol - * 3. Get FILE* to vol dev - * 4. Write to FILE* - */ - - ulib = libubi_open(); - if (ulib == NULL) { - rc = -PFIFLASH_ERR_UBI_OPEN; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - rc = bootenv_create(&bootenv_new); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_CREATE; - EBUF(PFIFLASH_ERRSTR[-rc], " 'new'"); - goto err; - } - - rc = bootenv_create(&bootenv_res); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_CREATE; - EBUF(PFIFLASH_ERRSTR[-rc], " 'res'"); - goto err; - } - - rc = bootenv_read_crc(fp_in, bootenv_new, fp_in_size, &crc); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_READ; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } else if (crc != pfi_crc) { - rc = -PFIFLASH_ERR_CRC_CHECK; - EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc); - goto err; - } - - rc = pdd_f(bootenv_old, bootenv_new, &bootenv_res, &warnings, - err_buf, err_buf_size); - if (rc != 0) { - EBUF_PREPEND("handling PDD"); - goto err; - } - else if (warnings) - /* TODO do something with warnings */ - dbg_msg("A warning in the PDD operation occured: %d", - warnings); - - rc = bootenv_size(bootenv_res, &update_size); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_SIZE; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); - - fd_out = open(path, O_RDWR); - if (fd_out < 0) { - rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; - EBUF(PFIFLASH_ERRSTR[-rc], id); - goto err; - } - fp_out = fdopen(fd_out, "r+"); - if (!fp_out) { - rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; - EBUF(PFIFLASH_ERRSTR[-rc], id); - goto err; - } - rc = ubi_update_start(ulib, fd_out, update_size); - if (rc < 0) { - rc = -PFIFLASH_ERR_UBI_VOL_UPDATE; - EBUF(PFIFLASH_ERRSTR[-rc], id); - goto err; - } - - rc = bootenv_write(fp_out, bootenv_res); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_WRITE; - EBUF(PFIFLASH_ERRSTR[-rc], devno, id); - goto err; - } - - err: - if (ulib != NULL) - libubi_close(ulib); - if (bootenv_new != NULL) - bootenv_destroy(&bootenv_new); - if (bootenv_res != NULL) - bootenv_destroy(&bootenv_res); - if (fp_out) - fclose(fp_out); - - return rc; -} - - -/** - * write_normal_volume - writes data from PFI file int to regular UBI volume - * @devno UBI device number - * @id UBI volume id - * @update_size size of data stream - * @fp_in PFI data file pointer - * @pfi_crc CRC data from PFI header - * - * Error handling: - * when UBI system couldn't be opened - * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err - * when UBI system couldn't open a volume - * - returns -PFIFLASH_ERR_UBI_VOL_FOPEN, err_buf matches text to err - * when unexpected EOF is encountered - * - returns -PFIFLASH_ERR_EOF, err_buf matches text to err - * when file I/O error - * - returns -PFIFLASH_ERR_FIO, err_buf matches text to err - * when CRC check fails - * - retruns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err - **/ -static int -write_normal_volume(int devno, uint32_t id, size_t update_size, FILE* fp_in, - uint32_t pfi_crc, - char *err_buf, size_t err_buf_size) -{ - int rc, fd_out; - uint32_t crc, crc32_table[256]; - char path[PATH_MAX]; - size_t bytes_left; - FILE* fp_out; - libubi_t ulib; - - rc = 0; - crc = UBI_CRC32_INIT; - bytes_left = update_size; - fp_out = NULL; - ulib = NULL; - - log_msg("[ ubiupdatevol id=%d, update_size=%d fp_in=%p", - id, update_size, fp_in); - - ulib = libubi_open(); - if (ulib == NULL) { - rc = -PFIFLASH_ERR_UBI_OPEN; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); - - fd_out = open(path, O_RDWR); - if (fd_out < 0) { - rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; - EBUF(PFIFLASH_ERRSTR[-rc], id); - goto err; - } - fp_out = fdopen(fd_out, "r+"); - if (!fp_out) { - rc = -PFIFLASH_ERR_UBI_VOL_FOPEN; - EBUF(PFIFLASH_ERRSTR[-rc], id); - goto err; - } - rc = ubi_update_start(ulib, fd_out, update_size); - if (rc < 0) { - rc = -PFIFLASH_ERR_UBI_VOL_UPDATE; - EBUF(PFIFLASH_ERRSTR[-rc], id); - goto err; - } - - init_crc32_table(crc32_table); - while (bytes_left) { - char buf[1024]; - size_t to_rw = sizeof buf > bytes_left ? - bytes_left : sizeof buf; - if (fread(buf, 1, to_rw, fp_in) != to_rw) { - rc = -PFIFLASH_ERR_EOF; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - crc = clc_crc32(crc32_table, crc, buf, to_rw); - if (fwrite(buf, 1, to_rw, fp_out) != to_rw) { - rc = -PFIFLASH_ERR_FIO; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - bytes_left -= to_rw; - } - - if (crc != pfi_crc) { - rc = -PFIFLASH_ERR_CRC_CHECK; - EBUF(PFIFLASH_ERRSTR[-rc], pfi_crc, crc); - goto err; - } - - err: - if (fp_out) - fclose(fp_out); - if (ulib) - libubi_close(ulib); - - return rc; -} - -static int compare_bootenv(FILE *fp_pfi, FILE **fp_flash, uint32_t ids_size, - uint32_t data_size, pdd_func_t pdd_f, char *err_buf, - size_t err_buf_size) -{ - int rc, warnings = 0; - unsigned int i; - bootenv_t bootenv_pfi, bootenv_res = NULL, bootenv_flash = NULL; - - rc = bootenv_create(&bootenv_pfi); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_CREATE; - goto err; - } - - rc = bootenv_create(&bootenv_res); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_CREATE; - goto err; - } - - rc = bootenv_read(fp_pfi, bootenv_pfi, data_size); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_READ; - goto err; - } - - for (i = 0; i < ids_size; i++) { - rc = bootenv_create(&bootenv_flash); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_CREATE; - goto err; - } - - rc = bootenv_read(fp_flash[i], bootenv_flash, BOOTENV_MAXSIZE); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_READ; - goto err; - } - - rc = pdd_f(bootenv_flash, bootenv_pfi, &bootenv_res, - &warnings, err_buf, err_buf_size); - if (rc != 0) { - rc = -PFIFLASH_ERR_PDD_UNKNOWN; - goto err; - } - - rc = bootenv_compare(bootenv_flash, bootenv_res); - if (rc > 0) { - rc = -PFIFLASH_CMP_DIFF; - goto err; - } else if (rc < 0) { - rc = -PFIFLASH_ERR_COMPARE; - goto err; - } - - bootenv_destroy(&bootenv_flash); - bootenv_flash = NULL; - } - -err: - if (bootenv_pfi) - bootenv_destroy(&bootenv_pfi); - if (bootenv_res) - bootenv_destroy(&bootenv_res); - if (bootenv_flash) - bootenv_destroy(&bootenv_flash); - - return rc; -} - -static int compare_data(FILE *fp_pfi, FILE **fp_flash, uint32_t ids_size, - uint32_t bytes_left) -{ - unsigned int i; - size_t read_bytes, rc = 0; - char buf_pfi[COMPARE_BUFFER_SIZE]; - char *buf_flash[ids_size]; - - for (i = 0; i < ids_size; i++) { - buf_flash[i] = malloc(COMPARE_BUFFER_SIZE); - if (!buf_flash[i]) - return -PFIFLASH_ERR_COMPARE; - } - - while (bytes_left) { - if (bytes_left > COMPARE_BUFFER_SIZE) - read_bytes = COMPARE_BUFFER_SIZE; - else - read_bytes = bytes_left; - - rc = fread(buf_pfi, 1, read_bytes, fp_pfi); - if (rc != read_bytes) { - rc = -PFIFLASH_ERR_COMPARE; - goto err; - } - - for (i = 0; i < ids_size; i++) { - rc = fread(buf_flash[i], 1, read_bytes, fp_flash[i]); - if (rc != read_bytes) { - rc = -PFIFLASH_CMP_DIFF; - goto err; - } - - rc = memcmp(buf_pfi, buf_flash[i], read_bytes); - if (rc != 0) { - rc = -PFIFLASH_CMP_DIFF; - goto err; - } - } - - bytes_left -= read_bytes; - } - -err: - for (i = 0; i < ids_size; i++) - free(buf_flash[i]); - - return rc; -} - -static int compare_volumes(int devno, pfi_ubi_t u, FILE *fp_pfi, - pdd_func_t pdd_f, char *err_buf, size_t err_buf_size) -{ - int rc, is_bootenv = 0; - unsigned int i; - char path[PATH_MAX]; - libubi_t ulib = NULL; - FILE *fp_flash[u->ids_size]; - - ulib = libubi_open(); - if (ulib == NULL) { - rc = -PFIFLASH_ERR_UBI_OPEN; - goto err; - } - - for (i = 0; i < u->ids_size; i++) { - if (u->ids[i] == EXAMPLE_BOOTENV_VOL_ID_1 || - u->ids[i] == EXAMPLE_BOOTENV_VOL_ID_2) - is_bootenv = 1; - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, u->ids[i]); - - fp_flash[i] = fopen(path, "r"); - if (fp_flash[i] == NULL) { - rc = -PFIFLASH_ERR_UBI_OPEN; - goto err; - } - } - - if (is_bootenv) - rc = compare_bootenv(fp_pfi, fp_flash, u->ids_size, - u->data_size, pdd_f, err_buf, err_buf_size); - else - rc = compare_data(fp_pfi, fp_flash, u->ids_size, u->data_size); - -err: - if (rc < 0) - EBUF(PFIFLASH_ERRSTR[-rc]); - - for (i = 0; i < u->ids_size; i++) - fclose(fp_flash[i]); - if (ulib) - libubi_close(ulib); - - return rc; -} - -static int -erase_mtd_region(FILE* file_p, int start, int length) -{ - int rc, fd; - erase_info_t erase; - mtd_info_t mtdinfo; - loff_t offset = start; - loff_t end = offset + length; - - fd = fileno(file_p); - if (fd < 0) - return -PFIFLASH_ERR_MTD_ERASE; - - rc = ioctl(fd, MEMGETINFO, &mtdinfo); - if (rc) - return -PFIFLASH_ERR_MTD_ERASE; - - /* check for bad blocks in case of NAND flash */ - if (mtdinfo.type == MTD_NANDFLASH) { - while (offset < end) { - rc = ioctl(fd, MEMGETBADBLOCK, &offset); - if (rc > 0) { - return -PFIFLASH_ERR_MTD_ERASE; - } - - offset += mtdinfo.erasesize; - } - } - - erase.start = start; - erase.length = length; - - rc = ioctl(fd, MEMERASE, &erase); - if (rc) { - return -PFIFLASH_ERR_MTD_ERASE; - } - - return rc; -} - -/** - * process_raw_volumes - writes the raw sections of the PFI data - * @pfi PFI data file pointer - * @pfi_raws list of PFI raw headers - * @rawdev device to use to write raw data - * - * Error handling: - * when early EOF in PFI data - * - returns -PFIFLASH_ERR_EOF, err_buf matches text to err - * when file I/O error - * - returns -PFIFLASH_ERR_FIO, err_buf matches text to err - * when CRC check fails - * - returns -PFIFLASH_ERR_CRC_CHECK, err_buf matches text to err - * when opening MTD device fails - * - reutrns -PFIFLASH_ERR_MTD_OPEN, err_buf matches text to err - * when closing MTD device fails - * - returns -PFIFLASH_ERR_MTD_CLOSE, err_buf matches text to err - **/ -static int -process_raw_volumes(FILE* pfi, list_t pfi_raws, const char* rawdev, - char* err_buf, size_t err_buf_size) -{ - int rc; - char *pfi_data; - void *i; - uint32_t crc, crc32_table[256]; - size_t j, k; - FILE* mtd = NULL; - list_t ptr; - - if (is_empty(pfi_raws)) - return 0; - - if (rawdev == NULL) - return 0; - - rc = 0; - - pfi_data = NULL; - - log_msg("[ rawupdate dev=%s", rawdev); - - crc = UBI_CRC32_INIT; - init_crc32_table(crc32_table); - - /* most likely only one element in list, but just in case */ - foreach(i, ptr, pfi_raws) { - pfi_raw_t r = (pfi_raw_t)i; - - /* read in pfi data */ - if (pfi_data != NULL) - free(pfi_data); - pfi_data = malloc(r->data_size * sizeof(char)); - for (j = 0; j < r->data_size; j++) { - int c = fgetc(pfi); - if (c == EOF) { - rc = -PFIFLASH_ERR_EOF; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } else if (ferror(pfi)) { - rc = -PFIFLASH_ERR_FIO; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - pfi_data[j] = (char)c; - } - crc = clc_crc32(crc32_table, crc, pfi_data, r->data_size); - - /* check crc */ - if (crc != r->crc) { - rc = -PFIFLASH_ERR_CRC_CHECK; - EBUF(PFIFLASH_ERRSTR[-rc], r->crc, crc); - goto err; - } - - /* open device */ - mtd = fopen(rawdev, "r+"); - if (mtd == NULL) { - rc = -PFIFLASH_ERR_MTD_OPEN; - EBUF(PFIFLASH_ERRSTR[-rc], rawdev); - goto err; - } - - for (j = 0; j < r->starts_size; j++) { - rc = erase_mtd_region(mtd, r->starts[j], r->data_size); - if (rc) { - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - fseek(mtd, r->starts[j], SEEK_SET); - for (k = 0; k < r->data_size; k++) { - int c = fputc((int)pfi_data[k], mtd); - if (c == EOF) { - fclose(mtd); - rc = -PFIFLASH_ERR_EOF; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - if ((char)c != pfi_data[k]) { - fclose(mtd); - rc = -1; - goto err; - } - } - } - rc = fclose(mtd); - mtd = NULL; - if (rc != 0) { - rc = -PFIFLASH_ERR_MTD_CLOSE; - EBUF(PFIFLASH_ERRSTR[-rc], rawdev); - goto err; - } - } - - err: - if (mtd != NULL) - fclose(mtd); - if (pfi_data != NULL) - free(pfi_data); - return rc; -} - - -/** - * erase_unmapped_ubi_volumes - skip volumes provided by PFI file, clear rest - * @devno UBI device number - * @pfi_ubis list of UBI header data - * - * Error handling: - * when UBI id is out of bounds - * - returns -PFIFLASH_ERR_UBI_VID_OOB, err_buf matches text to err - * when UBI volume can't be removed - * - passes rc, prepends err_buf with contextual aid - **/ -static int -erase_unmapped_ubi_volumes(int devno, list_t pfi_ubis, - char *err_buf, size_t err_buf_size) -{ - int rc; - uint8_t ubi_volumes[PFI_UBI_MAX_VOLUMES]; - size_t i; - list_t ptr; - pfi_ubi_t u; - - rc = 0; - - for (i = 0; i < PFI_UBI_MAX_VOLUMES; i++) - ubi_volumes[i] = 1; - - foreach(u, ptr, pfi_ubis) { - /* iterate over each vol_id */ - for(i = 0; i < u->ids_size; i++) { - if (u->ids[i] >= PFI_UBI_MAX_VOLUMES) { - rc = -PFIFLASH_ERR_UBI_VID_OOB; - EBUF(PFIFLASH_ERRSTR[-rc], u->ids[i]); - goto err; - } - /* remove from removal list */ - ubi_volumes[u->ids[i]] = 0; - } - } - - for (i = 0; i < PFI_UBI_MAX_VOLUMES; i++) { - if (ubi_volumes[i]) { - rc = my_ubi_rmvol(devno, i, err_buf, err_buf_size); - if (rc != 0) { - EBUF_PREPEND("remove volume failed"); - goto err; - } - } - } - - err: - return rc; -} - - -/** - * process_ubi_volumes - delegate tasks regarding UBI volumes - * @pfi PFI data file pointer - * @seqnum sequence number - * @pfi_ubis list of UBI header data - * @bootenv_old storage for current system PDD - * @pdd_f function to handle PDD - * @ubi_update_process whether reading or writing - * - * Error handling: - * when and unknown ubi_update_process is given - * - returns -PFIFLASH_ERR_UBI_UNKNOWN, err_buf matches text to err - * otherwise - * - passes rc and err_buf - **/ -static int -process_ubi_volumes(FILE* pfi, int seqnum, list_t pfi_ubis, - bootenv_t bootenv_old, pdd_func_t pdd_f, - ubi_update_process_t ubi_update_process, - char *err_buf, size_t err_buf_size) -{ - int rc; - pfi_ubi_t u; - list_t ptr; - - rc = 0; - - foreach(u, ptr, pfi_ubis) { - int s = seqnum; - - if (s > ((int)u->ids_size - 1)) - s = 0; /* per default use the first */ - u->curr_seqnum = s; - - switch (ubi_update_process) { - case UBI_REMOVE: - /* TODO are all these "EXAMPLE" vars okay? */ - if ((u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_1) || - (u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_2)) { - rc = read_bootenv_volume(EXAMPLE_UBI_DEVICE, - u->ids[s], bootenv_old, - err_buf, err_buf_size); - /* it's okay if there is no bootenv - * we're going to write one */ - if ((rc == -PFIFLASH_ERR_UBI_VOL_FOPEN) || - (rc == -PFIFLASH_ERR_BOOTENV_READ)) - rc = 0; - if (rc != 0) - goto err; - } - - rc = my_ubi_rmvol(EXAMPLE_UBI_DEVICE, u->ids[s], - err_buf, err_buf_size); - if (rc != 0) - goto err; - - break; - case UBI_WRITE: - rc = my_ubi_mkvol(EXAMPLE_UBI_DEVICE, s, u, - err_buf, err_buf_size); - if (rc != 0) { - EBUF_PREPEND("creating volume"); - goto err; - } - - if ((u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_1) || - (u->ids[s] == EXAMPLE_BOOTENV_VOL_ID_2)) { - rc = write_bootenv_volume(EXAMPLE_UBI_DEVICE, - u->ids[s], - bootenv_old, pdd_f, - pfi, - u->data_size, - u->crc, - err_buf, - err_buf_size); - if (rc != 0) - EBUF_PREPEND("bootenv volume"); - } else { - rc = write_normal_volume(EXAMPLE_UBI_DEVICE, - u->ids[s], - u->data_size, pfi, - u->crc, - err_buf, - err_buf_size); - if (rc != 0) - EBUF_PREPEND("normal volume"); - } - if (rc != 0) - goto err; - - break; - case UBI_COMPARE: - rc = compare_volumes(EXAMPLE_UBI_DEVICE, u, pfi, pdd_f, - err_buf, err_buf_size); - if (rc != 0) { - EBUF_PREPEND("compare volume"); - goto err; - } - - break; - default: - rc = -PFIFLASH_ERR_UBI_UNKNOWN; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - } - - err: - return rc; -} - - -/** - * mirror_ubi_volumes - mirror redundant pairs of volumes - * @devno UBI device number - * @pfi_ubis list of PFI header data - * - * Error handling: - * when UBI system couldn't be opened - * - returns -PFIFLASH_ERR_UBI_OPEN, err_buf matches text to err - **/ -static int -mirror_ubi_volumes(uint32_t devno, list_t pfi_ubis, - char *err_buf, size_t err_buf_size) -{ - int rc; - uint32_t j; - list_t ptr; - pfi_ubi_t i; - libubi_t ulib; - - rc = 0; - ulib = NULL; - - log_msg("[ mirror ..."); - - ulib = libubi_open(); - if (ulib == NULL) { - rc = -PFIFLASH_ERR_UBI_OPEN; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - /** - * Execute all mirror operations on redundant groups. - * Create a volume within a redundant group if it does - * not exist already (this is a precondition of - * ubimirror). - */ - foreach(i, ptr, pfi_ubis) { - for (j = 0; j < i->ids_size; j++) { - /* skip self-match */ - if (i->ids[j] == i->ids[i->curr_seqnum]) - continue; - - rc = my_ubi_rmvol(devno, i->ids[j], - err_buf, err_buf_size); - if (rc != 0) - goto err; - - rc = my_ubi_mkvol(devno, j, i, - err_buf, err_buf_size); - if (rc != 0) - goto err; - } - } - - foreach(i, ptr, pfi_ubis) { - rc = ubimirror(devno, i->curr_seqnum, i->ids, i->ids_size, - err_buf, err_buf_size); - if (rc != 0) - goto err; - } - - - err: - if (ulib != NULL) - libubi_close(ulib); - - return rc; -} - - -/** - * pfiflash_with_options - exposed func to flash memory with a PFI file - * @pfi PFI data file pointer - * @complete flag to erase unmapped volumes - * @seqnum sequence number - * @compare flag to compare - * @pdd_handling method to handle pdd (keep, merge, overwrite...) - * - * Error handling: - * when bootenv can't be created - * - returns -PFIFLASH_ERR_BOOTENV_CREATE, err_buf matches text to err - * when PFI headers can't be read, or - * when fail to skip raw sections, or - * when error occurs while processing raw volumes, or - * when fail to erase unmapped UBI vols, or - * when error occurs while processing UBI volumes, or - * when error occurs while mirroring UBI volumes - * - passes rc, prepends err_buf with contextual aid - **/ -int -pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare, - pdd_handling_t pdd_handling, const char* rawdev, - char *err_buf, size_t err_buf_size) -{ - int rc; - bootenv_t bootenv; - pdd_func_t pdd_f; - - if (pfi == NULL) - return -EINVAL; - - rc = 0; - pdd_f = NULL; - - /* If the user didnt specify a seqnum we start per default - * with the index 0 */ - int curr_seqnum = seqnum < 0 ? 0 : seqnum; - - list_t pfi_raws = mk_empty(); /* list of raw sections from a pfi */ - list_t pfi_ubis = mk_empty(); /* list of ubi sections from a pfi */ - - rc = bootenv_create(&bootenv); - if (rc != 0) { - rc = -PFIFLASH_ERR_BOOTENV_CREATE; - EBUF(PFIFLASH_ERRSTR[-rc], ""); - goto err; - } - - rc = read_pfi_headers(&pfi_raws, &pfi_ubis, pfi, err_buf, err_buf_size); - if (rc != 0) { - EBUF_PREPEND("reading PFI header"); - goto err; - } - - if (rawdev == NULL || compare) - rc = skip_raw_volumes(pfi, pfi_raws, err_buf, err_buf_size); - else - rc = process_raw_volumes(pfi, pfi_raws, rawdev, err_buf, - err_buf_size); - if (rc != 0) { - EBUF_PREPEND("handling raw section"); - goto err; - } - - if (complete && !compare) { - rc = erase_unmapped_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis, - err_buf, err_buf_size); - if (rc != 0) { - EBUF_PREPEND("deleting unmapped UBI volumes"); - goto err; - } - } - - if (((int)pdd_handling >= 0) && - (pdd_handling < PDD_HANDLING_NUM)) - pdd_f = pdd_funcs[pdd_handling]; - else { - rc = -PFIFLASH_ERR_PDD_UNKNOWN; - EBUF(PFIFLASH_ERRSTR[-rc]); - goto err; - } - - if (!compare) { - rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv, - pdd_f, UBI_REMOVE, err_buf, err_buf_size); - if (rc != 0) { - EBUF_PREPEND("removing UBI volumes"); - goto err; - } - - rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv, - pdd_f, UBI_WRITE, err_buf, err_buf_size); - if (rc != 0) { - EBUF_PREPEND("writing UBI volumes"); - goto err; - } - - if (seqnum < 0) { /* mirror redundant pairs */ - rc = mirror_ubi_volumes(EXAMPLE_UBI_DEVICE, pfi_ubis, - err_buf, err_buf_size); - if (rc != 0) { - EBUF_PREPEND("mirroring UBI volumes"); - goto err; - } - } - } else { - /* only compare volumes, don't alter the content */ - rc = process_ubi_volumes(pfi, curr_seqnum, pfi_ubis, bootenv, - pdd_f, UBI_COMPARE, err_buf, err_buf_size); - - if (rc == -PFIFLASH_CMP_DIFF) - /* update is necessary, return positive value */ - rc = 1; - - if (rc < 0) { - EBUF_PREPEND("comparing UBI volumes"); - goto err; - } - } - - err: - pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws); - pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis); - bootenv_destroy(&bootenv); - return rc; -} - - -/** - * pfiflash - passes to pfiflash_with_options - * @pfi PFI data file pointer - * @complete flag to erase unmapped volumes - * @seqnum sequence number - * @pdd_handling method to handle pdd (keep, merge, overwrite...) - **/ -int -pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling, - char *err_buf, size_t err_buf_size) -{ - return pfiflash_with_options(pfi, complete, seqnum, 0, pdd_handling, - NULL, err_buf, err_buf_size); -} diff --git a/ubi-utils/sort-me-out/libubigen-old.c b/ubi-utils/sort-me-out/libubigen-old.c deleted file mode 100644 index 6aef291..0000000 --- a/ubi-utils/sort-me-out/libubigen-old.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - * - * Add UBI headers to binary data. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <mtd/ubi-header.h> - -#include "config.h" -#include "ubigen.h" -#include "crc32.h" - -#define UBI_NAME_SIZE 256 -#define DEFAULT_VID_OFFSET ((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE)) -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -static uint32_t crc32_table[256]; - -struct ubi_info { - struct ubi_vid_hdr* v; /* Volume ID header */ - struct ubi_ec_hdr* ec; /* Erase count header */ - - FILE* fp_in; /* Input Stream */ - FILE* fp_out; /* Output stream */ - - size_t peb_size; /* Physical EB size in bytes */ - size_t leb_size; /* Size of a logical EB in a physical EB */ - size_t leb_total; /* Total input size in logical EB */ - size_t alignment; /* Block alignment */ - size_t data_pad; /* Size of padding in each physical EB */ - - size_t bytes_total; /* Total input size in bytes */ - size_t bytes_read; /* Nymber of read bytes (total) */ - - uint32_t blks_written; /* Number of written logical EB */ - - uint8_t* buf; /* Allocated buffer */ - uint8_t* ptr_ec_hdr; /* Pointer to EC hdr in buf */ - uint8_t* ptr_vid_hdr; /* Pointer to VID hdr in buf */ - uint8_t* ptr_data; /* Pointer to data region in buf */ -}; - - -static uint32_t -byte_to_blk(uint64_t byte, uint32_t peb_size) -{ - return (byte % peb_size) == 0 - ? (byte / peb_size) - : (byte / peb_size) + 1; -} - -static int -validate_ubi_info(ubi_info_t u) -{ - if ((u->v->vol_type != UBI_VID_DYNAMIC) && - (u->v->vol_type != UBI_VID_STATIC)) { - return EUBIGEN_INVALID_TYPE; - } - - if (__be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) { - return EUBIGEN_INVALID_HDR_OFFSET; - } - - return 0; -} - -static int -skip_blks(ubi_info_t u, uint32_t blks) -{ - uint32_t i; - size_t read = 0, to_read = 0; - - /* Step to a maximum of leb_total - 1 to keep the - restrictions. */ - for (i = 0; i < MIN(blks, u->leb_total-1); i++) { - /* Read in data */ - to_read = MIN(u->leb_size, - (u->bytes_total - u->bytes_read)); - read = fread(u->ptr_data, 1, to_read, u->fp_in); - if (read != to_read) { - return -EIO; - } - u->bytes_read += read; - u->blks_written++; - } - - return 0; -} - -static void -clear_buf(ubi_info_t u) -{ - memset(u->buf, 0xff, u->peb_size); -} - -static void -write_ec_hdr(ubi_info_t u) -{ - memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE); -} - -static int -fill_data_buffer_from_file(ubi_info_t u, size_t* read) -{ - size_t to_read = 0; - - if (u-> fp_in == NULL) - return -EIO; - - to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read)); - *read = fread(u->ptr_data, 1, to_read, u->fp_in); - if (*read != to_read) { - return -EIO; - } - return 0; -} - -static void -add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action) -{ - uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, - u->ptr_data, data_size); - - u->v->data_size = __cpu_to_be32(data_size); - u->v->data_crc = __cpu_to_be32(crc); - - if (action & BROKEN_DATA_CRC) { - u->v->data_crc = - __cpu_to_be32(__be32_to_cpu(u->v->data_crc) + 1); - } - if (action & BROKEN_DATA_SIZE) { - u->v->data_size = - __cpu_to_be32(__be32_to_cpu(u->v->data_size) + 1); - } -} - -static void -write_vid_hdr(ubi_info_t u, ubigen_action_t action) -{ - uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, - u->v, UBI_VID_HDR_SIZE_CRC); - /* Write VID header */ - u->v->hdr_crc = __cpu_to_be32(crc); - if (action & BROKEN_HDR_CRC) { - u->v->hdr_crc = __cpu_to_be32(__be32_to_cpu(u->v->hdr_crc) + 1); - } - memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE); -} - -static int -write_to_output_stream(ubi_info_t u) -{ - size_t written; - - written = fwrite(u->buf, 1, u->peb_size, u->fp_out); - if (written != u->peb_size) { - return -EIO; - } - return 0; -} - -int -ubigen_write_leb(ubi_info_t u, ubigen_action_t action) -{ - int rc = 0; - size_t read = 0; - - clear_buf(u); - write_ec_hdr(u); - - rc = fill_data_buffer_from_file(u, &read); - if (rc != 0) - return rc; - - if (u->v->vol_type == UBI_VID_STATIC) { - add_static_info(u, read, action); - } - - u->v->lnum = __cpu_to_be32(u->blks_written); - - if (action & MARK_AS_UPDATE) { - u->v->copy_flag = (u->v->copy_flag)++; - } - - write_vid_hdr(u, action); - rc = write_to_output_stream(u); - if (rc != 0) - return rc; - - /* Update current handle */ - u->bytes_read += read; - u->blks_written++; - return 0; -} - -int -ubigen_write_complete(ubi_info_t u) -{ - size_t i; - int rc = 0; - - for (i = 0; i < u->leb_total; i++) { - rc = ubigen_write_leb(u, NO_ERROR); - if (rc != 0) - return rc; - } - - return 0; -} - -int -ubigen_write_broken_update(ubi_info_t u, uint32_t blk) -{ - int rc = 0; - - rc = skip_blks(u, blk); - if (rc != 0) - return rc; - - rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC); - if (rc != 0) - return rc; - - - return 0; -} - -void -dump_info(ubi_info_t u ubi_unused) -{ -#ifdef DEBUG - int err = 0; - if (!u) { - fprintf(stderr, "<empty>"); - return; - } - if (!u->ec) { - fprintf(stderr, "<ec-empty>"); - err = 1; - } - if (!u->v) { - fprintf(stderr, "<v-empty>"); - err = 1; - } - if (err) return; - - fprintf(stderr, "ubi volume\n"); - fprintf(stderr, "version : %8d\n", u->v->version); - fprintf(stderr, "vol_id : %8d\n", __be32_to_cpu(u->v->vol_id)); - fprintf(stderr, "vol_type : %8s\n", - u->v->vol_type == UBI_VID_STATIC ? - "static" : "dynamic"); - fprintf(stderr, "used_ebs : %8d\n", - __be32_to_cpu(u->v->used_ebs)); - fprintf(stderr, "peb_size : 0x%08x\n", u->peb_size); - fprintf(stderr, "leb_size : 0x%08x\n", u->leb_size); - fprintf(stderr, "data_pad : 0x%08x\n", - __be32_to_cpu(u->v->data_pad)); - fprintf(stderr, "leb_total : %8d\n", u->leb_total); - fprintf(stderr, "header offs : 0x%08x\n", - __be32_to_cpu(u->ec->vid_hdr_offset)); - fprintf(stderr, "bytes_total : %8d\n", u->bytes_total); - fprintf(stderr, " + in MiB : %8.2f M\n", - ((float)(u->bytes_total)) / 1024 / 1024); - fprintf(stderr, "-------------------------------\n\n"); -#else - return; -#endif -} - -int -ubigen_destroy(ubi_info_t *u) -{ - if (u == NULL) - return -EINVAL; - - ubi_info_t tmp = *u; - - if (tmp) { - if (tmp->v) - free(tmp->v); - if (tmp->ec) - free(tmp->ec); - if (tmp->buf) - free(tmp->buf); - free(tmp); - } - *u = NULL; - return 0; -} - -void -ubigen_init(void) -{ - init_crc32_table(crc32_table); -} - -int -ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type, - uint32_t peb_size, uint64_t ec, uint32_t alignment, - uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag, - size_t data_size, FILE* fp_in, FILE* fp_out) -{ - int rc = 0; - ubi_info_t res = NULL; - uint32_t crc; - uint32_t data_offset; - - if (alignment == 0) { - rc = EUBIGEN_INVALID_ALIGNMENT; - goto ubigen_create_err; - } - if ((fp_in == NULL) || (fp_out == NULL)) { - rc = -EINVAL; - goto ubigen_create_err; - } - - res = (ubi_info_t) calloc(1, sizeof(struct ubi_info)); - if (res == NULL) { - rc = -ENOMEM; - goto ubigen_create_err; - } - - res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr)); - if (res->v == NULL) { - rc = -ENOMEM; - goto ubigen_create_err; - } - - res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr)); - if (res->ec == NULL) { - rc = -ENOMEM; - goto ubigen_create_err; - } - - /* data which is needed in the general process */ - vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET; - data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE; - res->bytes_total = data_size; - res->peb_size = peb_size ? peb_size : DEFAULT_BLOCKSIZE; - res->data_pad = (res->peb_size - data_offset) % alignment; - res->leb_size = res->peb_size - data_offset - res->data_pad; - res->leb_total = byte_to_blk(data_size, res->leb_size); - res->alignment = alignment; - - if ((res->peb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) { - rc = EUBIGEN_TOO_SMALL_EB; - goto ubigen_create_err; - } - res->fp_in = fp_in; - res->fp_out = fp_out; - - /* vid hdr data which doesn't change */ - res->v->magic = __cpu_to_be32(UBI_VID_HDR_MAGIC); - res->v->version = version ? version : UBI_VERSION; - res->v->vol_type = vol_type; - res->v->vol_id = __cpu_to_be32(vol_id); - res->v->compat = compat_flag; - res->v->data_pad = __cpu_to_be32(res->data_pad); - - /* static only: used_ebs */ - if (res->v->vol_type == UBI_VID_STATIC) { - res->v->used_ebs = __cpu_to_be32(byte_to_blk - (res->bytes_total, - res->leb_size)); - } - - /* ec hdr (fixed, doesn't change) */ - res->ec->magic = __cpu_to_be32(UBI_EC_HDR_MAGIC); - res->ec->version = version ? version : UBI_VERSION; - res->ec->ec = __cpu_to_be64(ec); - res->ec->vid_hdr_offset = __cpu_to_be32(vid_hdr_offset); - - res->ec->data_offset = __cpu_to_be32(data_offset); - - crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec, - UBI_EC_HDR_SIZE_CRC); - res->ec->hdr_crc = __cpu_to_be32(crc); - - /* prepare a read buffer */ - res->buf = (uint8_t*) malloc (res->peb_size * sizeof(uint8_t)); - if (res->buf == NULL) { - rc = -ENOMEM; - goto ubigen_create_err; - } - - /* point to distinct regions within the buffer */ - res->ptr_ec_hdr = res->buf; - res->ptr_vid_hdr = res->buf + __be32_to_cpu(res->ec->vid_hdr_offset); - res->ptr_data = res->buf + __be32_to_cpu(res->ec->vid_hdr_offset) - + UBI_VID_HDR_SIZE; - - rc = validate_ubi_info(res); - if (rc != 0) { - fprintf(stderr, "Volume validation failed: %d\n", rc); - goto ubigen_create_err; - } - - dump_info(res); - *u = res; - return rc; - -ubigen_create_err: - if (res) { - if (res->v) - free(res->v); - if (res->ec) - free(res->ec); - if (res->buf) - free(res->buf); - free(res); - } - *u = NULL; - return rc; -} - -int -ubigen_get_leb_size(ubi_info_t u, size_t* size) -{ - if (u == NULL) - return -EINVAL; - - *size = u->leb_size; - return 0; -} - - -int -ubigen_get_leb_total(ubi_info_t u, size_t* total) -{ - if (u == NULL) - return -EINVAL; - - *total = u->leb_total; - return 0; -} - -int -ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes, - const char* vol_name, struct ubi_vtbl_record *lvol_rec) -{ - uint32_t crc; - - if ((u == NULL) || (vol_name == NULL)) - return -EINVAL; - - memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE); - - lvol_rec->reserved_pebs = - __cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size)); - lvol_rec->alignment = __cpu_to_be32(u->alignment); - lvol_rec->data_pad = u->v->data_pad; - lvol_rec->vol_type = u->v->vol_type; - - lvol_rec->name_len = - __cpu_to_be16((uint16_t)strlen((const char*)vol_name)); - - memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1); - - crc = clc_crc32(crc32_table, UBI_CRC32_INIT, - lvol_rec, UBI_VTBL_RECORD_SIZE_CRC); - lvol_rec->crc = __cpu_to_be32(crc); - - return 0; -} diff --git a/ubi-utils/sort-me-out/libubimirror.c b/ubi-utils/sort-me-out/libubimirror.c deleted file mode 100644 index d06770e..0000000 --- a/ubi-utils/sort-me-out/libubimirror.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdio.h> -#include <errno.h> -#include <unistd.h> -#include <memory.h> -#include <limits.h> -#include <fcntl.h> - -#include <libubi.h> -#include "ubimirror.h" - -#define COMPARE_BUF_SIZE (128 * 1024) - -#define DEFAULT_DEV_PATTERN "/dev/ubi%d" -#define DEFAULT_VOL_PATTERN "/dev/ubi%d_%d" - -#define EBUF(fmt...) do { \ - snprintf(err_buf, err_buf_size, fmt); \ -} while (0) - -enum { - compare_error = -1, - seek_error = -2, - write_error = -3, - read_error = -4, - update_error = -5, - ubi_error = -6, - open_error = -7, - close_error = -8, - compare_equal = 0, - compare_different = 1 -}; - -/* - * Read len number of bytes from fd. - * Return 0 on EOF, -1 on error. - */ -static ssize_t fill_buffer(int fd, unsigned char *buf, ssize_t len) -{ - ssize_t got, have = 0; - - do { - got = read(fd, buf + have, len - have); - if (got == -1 && errno != EINTR) - return -1; - have += got; - } while (got > 0 && have < len); - return have; -} - -/* - * Write len number of bytes to fd. - * Return bytes written (>= 0), -1 on error. - */ -static ssize_t flush_buffer(int fd, unsigned char *buf, ssize_t len) -{ - ssize_t done, have = 0; - - do { - done = write(fd, buf + have, len - have); - if (done == -1 && errno != EINTR) - return -1; - have += done; - } while (done > 0 && have < len); - return have; -} - -/* - * Compare two files. Return 0, 1, or -1, depending on whether the - * files are equal, different, or an error occured. - * Return compare-different when target volume can not be read. Might be - * an interrupted volume update and then the target device returns -EIO but - * can be updated. - * - * fd_a is source - * fd_b is destination - */ -static int compare_files(int fd_a, int fd_b) -{ - unsigned char buf_a[COMPARE_BUF_SIZE], buf_b[COMPARE_BUF_SIZE]; - ssize_t len_a, len_b; - int rc; - - for (;;) { - len_a = fill_buffer(fd_a, buf_a, sizeof(buf_a)); - if (len_a == -1) { - rc = compare_error; - break; - } - len_b = fill_buffer(fd_b, buf_b, sizeof(buf_b)); - if (len_b == -1) { - rc = compare_different; - break; - } - if (len_a != len_b) { - rc = compare_different; - break; - } - if (len_a == 0) { /* Size on both files equal and EOF */ - rc = compare_equal; - break; - } - if (memcmp(buf_a, buf_b, len_a) != 0 ) { - rc = compare_different; - break; - } - } - /* Position both files at the beginning */ - if (lseek(fd_a, 0, SEEK_SET) == -1 || - lseek(fd_b, 0, SEEK_SET) == -1) - rc = seek_error; - return rc; -} - -int vol_get_used_bytes(int vol_fd, unsigned long long *bytes) -{ - off_t res; - - res = lseek(vol_fd, 0, SEEK_END); - if (res == (off_t)-1) - return -1; - *bytes = (unsigned long long) res; - res = lseek(vol_fd, 0, SEEK_SET); - return res == (off_t)-1 ? -1 : 0; -} - -static int copy_files(libubi_t ulib, int fd_in, int fd_out) -{ - unsigned char buf_a[COMPARE_BUF_SIZE]; - ssize_t len_a, len_b; - unsigned long long update_size, copied; - - if (vol_get_used_bytes(fd_in, &update_size) == -1 || - ubi_update_start(ulib, fd_out, update_size) == -1) - return update_error; - for (copied = 0; copied < update_size; copied += len_b ) { - len_a = fill_buffer(fd_in, buf_a, sizeof(buf_a)); - if (len_a == -1) - return read_error; - if (len_a == 0) /* Reach EOF */ - return 0; - len_b = flush_buffer(fd_out, buf_a, len_a); - if (len_b != len_a) - return write_error; - } - return 0; -} - -int ubimirror(uint32_t devno, int seqnum, uint32_t *ids, ssize_t ids_size, - char *err_buf, size_t err_buf_size) -{ - int rc = 0; - uint32_t src_id; - char path[PATH_MAX]; - libubi_t ulib; - int fd_in = -1, i = 0, fd_out = -1; - - if (ids_size == 0) - return 0; - else { - if ((seqnum < 0) || (seqnum > (ids_size - 1))) { - EBUF("volume id %d out of range", seqnum); - return EUBIMIRROR_NO_SRC; - } - src_id = ids[seqnum]; - } - - ulib = libubi_open(); - if (ulib == NULL) - return ubi_error; - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, src_id); - - fd_in = open(path, O_RDONLY); - if (fd_in == -1) { - EBUF("open error source volume %d", ids[i]); - rc = open_error; - goto err; - } - - for (i = 0; i < ids_size; i++) { - if (ids[i] == src_id) /* skip self-mirror */ - continue; - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, ids[i]); - - fd_out = open(path, O_RDWR); - if (fd_out < 0){ - EBUF("open error destination volume %d", ids[i]); - rc = open_error; - goto err; - } - rc = compare_files(fd_in, fd_out); - if (rc < 0) { - EBUF("compare error volume %d and %d", src_id, ids[i]); - goto err; - } else if (rc == compare_different) { - rc = copy_files(ulib, fd_in, fd_out); - if (rc != 0) { - EBUF("mirror error volume %d to %d", src_id, - ids[i]); - goto err; - } - } - if ((rc = close(fd_out)) == -1) { - EBUF("close error volume %d", ids[i]); - rc = close_error; - goto err; - } else - fd_out = -1; - } -err: - if (fd_out != -1) - close(fd_out); - if (fd_in != -1) - close(fd_in); - if (ulib != NULL) - libubi_close(ulib); - return rc; -} diff --git a/ubi-utils/sort-me-out/list.c b/ubi-utils/sort-me-out/list.c deleted file mode 100644 index 6eb716b..0000000 --- a/ubi-utils/sort-me-out/list.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -#include <stdlib.h> -#include <assert.h> -#include <stdio.h> - -#include "list.h" - -list_t -mk_empty(void) -{ - return (list_t) NULL; -} - -int -is_empty(list_t l) -{ - return l == NULL; -} - -info_t -head(list_t l) -{ - assert(!is_empty(l)); - return l->info; -} - -list_t -tail(list_t l) -{ - assert(!is_empty(l)); - return l->next; -} - -list_t -remove_head(list_t l) -{ - list_t res; - assert(!is_empty(l)); - - res = l->next; - free(l); - return res; -} - -list_t -cons(info_t e, list_t l) -{ - list_t res = malloc(sizeof(*l)); - if (!res) - return NULL; - res->info = e; - res->next = l; - - return res; -} - -list_t -prepend_elem(info_t e, list_t l) -{ - return cons(e,l); -} - -list_t -append_elem(info_t e, list_t l) -{ - if (is_empty(l)) { - return cons(e,l); - } - l->next = append_elem(e, l->next); - - return l; -} - -list_t -insert_sorted(cmp_func_t cmp, info_t e, list_t l) -{ - if (is_empty(l)) - return cons(e, l); - - switch (cmp(e, l->info)) { - case -1: - case 0: - return l; - break; - case 1: - l->next = insert_sorted(cmp, e, l); - break; - default: - break; - } - - /* never reached */ - return NULL; -} - -list_t -remove_all(free_func_t free_func, list_t l) -{ - if (is_empty(l)) - return l; - list_t lnext = l->next; - - if (free_func && l->info) { - free_func(&(l->info)); - } - free(l); - - return remove_all(free_func, lnext); -} - - -info_t -is_in(cmp_func_t cmp, info_t e, list_t l) -{ - return - (is_empty(l)) - ? NULL - : (cmp(e, l->info)) == 0 ? l->info : is_in(cmp, e, l->next); -} - - -void -apply(process_func_t process_func, list_t l) -{ - list_t ptr; - void *i; - foreach(i, ptr, l) { - process_func(i); - } -} diff --git a/ubi-utils/sort-me-out/list.h b/ubi-utils/sort-me-out/list.h deleted file mode 100644 index e8452a2..0000000 --- a/ubi-utils/sort-me-out/list.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __LIST_H__ -#define __LIST_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -#include <stdint.h> - -#define foreach(elem, ptr, list) \ - for (elem = list != NULL ? (typeof(elem)) head(list) \ - : NULL, ptr = list; \ - ptr != NULL; \ - ptr = tail(ptr), \ - elem = (typeof(elem)) ptr ? head(ptr) : NULL) - -typedef struct node* list_t; -typedef void* info_t; -typedef int (*free_func_t)(info_t*); -typedef int (*cmp_func_t)(info_t, info_t); -typedef void (*process_func_t)(info_t); - -struct node { - list_t next; - info_t info; -}; - -list_t mk_empty(void); -int is_empty(list_t l); -info_t is_in(cmp_func_t cmp, info_t e, list_t l); -info_t head(list_t l); -list_t tail(list_t l); -list_t remove_head(list_t l); -list_t cons(info_t e, list_t l); -list_t prepend_elem(info_t e, list_t); -list_t append_elem(info_t e, list_t); -list_t remove_all(free_func_t free_func, list_t l); -list_t insert_sorted(cmp_func_t cmp_func, info_t e, list_t l); -void apply(process_func_t process_func, list_t l); - -#endif /* __LIST_H__ */ diff --git a/ubi-utils/sort-me-out/mkbootenv.c b/ubi-utils/sort-me-out/mkbootenv.c deleted file mode 100644 index 952f651..0000000 --- a/ubi-utils/sort-me-out/mkbootenv.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - * - * Create boot-parameter/pdd data from an ASCII-text input file. - * - * 1.2 Removed argp because we want to use uClibc. - * 1.3 Minor cleanup - */ - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <getopt.h> -#include <unistd.h> -#include <errno.h> -#include <mtd/ubi-header.h> - -#include "config.h" -#include "bootenv.h" -#include "error.h" - -#define PROGRAM_VERSION "1.3" - -static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" - "mkbootenv - processes bootenv text files and convertes " - "them into a binary format.\n"; - -static const char copyright [] __attribute__((unused)) = - "Copyright (c) International Business Machines Corp., 2006"; - -static const char *optionsstr = -" -c, --copyright Print copyright informatoin.\n" -" -o, --output=<fname> Write the output data to <output> instead of\n" -" stdout.\n" -" -?, --help Give this help list\n" -" --usage Give a short usage message\n" -" -V, --version Print program version\n"; - -static const char *usage = -"Usage: mkbootenv [-c?V] [-o <output>] [--copyright] [--output=<output>]\n" -" [--help] [--usage] [--version] [bootenv-txt-file]\n"; - -struct option long_options[] = { - { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, - { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, - { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0} -}; - -typedef struct myargs { - FILE* fp_in; - FILE* fp_out; - - char *arg1; - char **options; /* [STRING...] */ -} myargs; - -static int -parse_opt(int argc, char **argv, myargs *args) -{ - while (1) { - int key; - - key = getopt_long(argc, argv, "co:?V", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'c': - fprintf(stderr, "%s\n", copyright); - exit(0); - break; - case 'o': - args->fp_out = fopen(optarg, "wb"); - if ((args->fp_out) == NULL) { - fprintf(stderr, "Cannot open file %s " - "for output\n", optarg); - exit(1); - } - break; - case '?': /* help */ - printf("%s", doc); - printf("%s", optionsstr); - printf("\nReport bugs to %s\n", - PACKAGE_BUGREPORT); - exit(0); - break; - case 'V': - printf("%s\n", PROGRAM_VERSION); - exit(0); - break; - default: - printf("%s", usage); - exit(-1); - } - } - - if (optind < argc) { - args->fp_in = fopen(argv[optind++], "rb"); - if ((args->fp_in) == NULL) { - fprintf(stderr, "Cannot open file %s for input\n", - argv[optind]); - exit(1); - } - } - - return 0; -} - -int -main(int argc, char **argv) { - int rc = 0; - bootenv_t env; - - myargs args = { - .fp_in = stdin, - .fp_out = stdout, - .arg1 = NULL, - .options = NULL, - }; - - parse_opt(argc, argv, &args); - - rc = bootenv_create(&env); - if (rc != 0) { - err_msg("Cannot create bootenv handle."); - goto err; - } - rc = bootenv_read_txt(args.fp_in, env); - if (rc != 0) { - err_msg("Cannot read bootenv from input file."); - goto err; - } - rc = bootenv_write(args.fp_out, env); - if (rc != 0) { - err_msg("Cannot write bootenv to output file."); - goto err; - } - - if (args.fp_in != stdin) { - fclose(args.fp_in); - } - if (args.fp_out != stdout) { - fclose(args.fp_out); - } - -err: - bootenv_destroy(&env); - return rc; -} diff --git a/ubi-utils/sort-me-out/nand2bin.c b/ubi-utils/sort-me-out/nand2bin.c deleted file mode 100644 index 8c95b27..0000000 --- a/ubi-utils/sort-me-out/nand2bin.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006, 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Frank Haverkamp - * - * An utility to decompose NAND images and strip OOB off. Not yet finished ... - * - * 1.2 Removed argp because we want to use uClibc. - * 1.3 Minor cleanup - * 1.4 Fixed OOB output file - * 1.5 Added verbose output and option to set blocksize. - * Added split block mode for more convenient analysis. - * 1.6 Fixed ECC error detection and correction. - * 1.7 Made NAND ECC layout configurable, the holes which were previously - * filled with 0x00 are untouched now and will be 0xff just like MTD - * behaves when writing the oob (haver) - */ - -#include <config.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdint.h> -#include <getopt.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "config.h" -#include "nandecc.h" -#include "ecclayouts.h" - -#define PROGRAM_VERSION "1.7" - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#define MAXPATH 1024 -#define MIN(x,y) ((x)<(y)?(x):(y)) - -struct args { - const char *oob_file; - const char *output_file; - size_t pagesize; - size_t oobsize; - int bad_marker_offs_in_oob; - size_t blocksize; - int split_blocks; - size_t in_len; /* size of input file */ - int correct_ecc; - struct nand_ecclayout *nand_oob; - - /* special stuff needed to get additional arguments */ - char *arg1; - char **options; /* [STRING...] */ -}; - -static struct args myargs = { - .output_file = "data.bin", - .oob_file = "oob.bin", - .pagesize = 2048, - .blocksize = 128 * 1024, - .nand_oob = &ibm_nand_oob_64, - .in_len = 0, - .split_blocks = 0, - .correct_ecc = 0, - .arg1 = NULL, - .options = NULL, -}; - -static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" - "nand2bin - split data and OOB.\n"; - -static const char *optionsstr = -" -l, --ecc-placement=<MTD,IBM> OOB placement scheme (default is IBM).\n" -" -o, --output=<output> Data output file\n" -" -O, --oob=<oob> OOB output file\n" -" -p, --pagesize=<pagesize> NAND pagesize\n" -" -b, --blocksize=<blocksize> NAND blocksize\n" -" -s, --split-blocks generate binaries for each block\n" -" -e, --correct-ecc Correct data according to ECC info\n" -" -v, --verbose verbose output\n" -" -?, --help Give this help list\n" -" --usage Give a short usage message\n"; - -static const char *usage = -"Usage: nand2bin [-?] [-o <output>] [-O <oob>] [-p <pagesize>]\n" -" [--output=<output>] [--oob=<oob>] [--pagesize=<pagesize>] [--help]\n" -" [--usage] input.mif\n"; - -static int verbose = 0; - -static struct option long_options[] = { - { .name = "ecc-layout", .has_arg = 1, .flag = NULL, .val = 'l' }, - { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, - { .name = "oob", .has_arg = 1, .flag = NULL, .val = 'O' }, - { .name = "pagesize", .has_arg = 1, .flag = NULL, .val = 'p' }, - { .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'b' }, - { .name = "split-blocks", .has_arg = 0, .flag = NULL, .val = 's' }, - { .name = "correct-ecc", .has_arg = 0, .flag = NULL, .val = 'e' }, - { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, - { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, - { NULL, 0, NULL, 0} -}; - -/* - * str_to_num - Convert string into number and cope with endings like - * k, K, kib, KiB for kilobyte - * m, M, mib, MiB for megabyte - */ -static uint32_t str_to_num(char *str) -{ - char *s = str; - ulong num = strtoul(s, &s, 0); - - if (*s != '\0') { - if (strcmp(s, "KiB") == 0) - num *= 1024; - else if (strcmp(s, "MiB") == 0) - num *= 1024*1024; - else { - fprintf(stderr, "WARNING: Wrong number format " - "\"%s\", check your paramters!\n", str); - } - } - return num; -} - -/* - * @brief Parse the arguments passed into the test case. - * - * @param argc The number of arguments - * @param argv The argument list - * @param args Pointer to program args structure - * - * @return error - * - */ -static int parse_opt(int argc, char **argv, struct args *args) -{ - unsigned int i, oob_idx = 0; - const char *ecc_layout = NULL; - - while (1) { - int key; - - key = getopt_long(argc, argv, "b:el:o:O:p:sv?", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'b': /* --blocksize<blocksize> */ - args->blocksize = str_to_num(optarg); - break; - case 'e': /* --correct-ecc */ - args->correct_ecc = 1; - break; - case 'l': /* --ecc-layout=<...> */ - ecc_layout = optarg; - break; - case 'o': /* --output=<output.bin> */ - args->output_file = optarg; - break; - case 'O': /* --oob=<oob.bin> */ - args->oob_file = optarg; - break; - case 'p': /* --pagesize<pagesize> */ - args->pagesize = str_to_num(optarg); - break; - case 's': /* --split-blocks */ - args->split_blocks = 1; - break; - case 'v': /* --verbose */ - verbose++; - break; - case 'V': - printf("%s\n", PROGRAM_VERSION); - exit(0); - break; - case '?': /* help */ - printf("Usage: nand2bin [OPTION...] input.mif\n"); - printf("%s%s", doc, optionsstr); - printf("\nReport bugs to %s\n", - PACKAGE_BUGREPORT); - exit(0); - break; - default: - printf("%s", usage); - exit(-1); - } - } - - if (optind < argc) - args->arg1 = argv[optind++]; - - switch (args->pagesize) { - case 512: - args->oobsize = 16; - args->bad_marker_offs_in_oob = 5; - oob_idx = 0; - break; - case 2048: - args->oobsize = 64; - args->bad_marker_offs_in_oob = 0; - oob_idx = 1; - break; - default: - fprintf(stderr, "Unsupported page size: %d\n", args->pagesize); - return -EINVAL; - } - - /* Figure out correct oob layout if it differs from default */ - if (ecc_layout) { - for (i = 0; i < ARRAY_SIZE(oob_placement); i++) - if (strcmp(ecc_layout, oob_placement[i].name) == 0) - args->nand_oob = - oob_placement[i].nand_oob[oob_idx]; - } - return 0; -} - -/* - * We must only compare the relevant bytes in the OOB area. All other - * bytes can be ignored. The information we need to do this is in - * nand_oob. - */ -static int oob_cmp(struct nand_ecclayout *nand_oob, uint8_t *oob, - uint8_t *calc_oob) -{ - unsigned int i; - for (i = 0; i < nand_oob->eccbytes; i++) - if (oob[nand_oob->eccpos[i]] != calc_oob[nand_oob->eccpos[i]]) - return 1; - return 0; -} - -static inline void hexdump(FILE *fp, const uint8_t *buf, ssize_t size) -{ - int k; - - for (k = 0; k < size; k++) { - fprintf(fp, "%02x ", buf[k]); - if ((k & 15) == 15) - fprintf(fp, "\n"); - } -} - -static int process_page(struct args *args, uint8_t *buf, uint8_t *oobbuf) -{ - size_t i, j; - int eccpoi; - uint8_t ecc_code[3] = { 0, }; /* temp */ - - /* Calculate ECC */ - memset(oobbuf, 0xff, args->oobsize); - for (eccpoi = 0, i = 0; i < args->pagesize; i += 256, eccpoi += 3) { - nand_calculate_ecc(&buf[i], ecc_code); - for (j = 0; j < 3; j++) - oobbuf[args->nand_oob->eccpos[eccpoi + j]] = ecc_code[j]; - } - return 0; -} - -static int decompose_image(struct args *args, FILE *in_fp, - FILE *bin_fp, FILE *oob_fp) -{ - unsigned int i, eccpoi; - int read, rc, page = 0; - uint8_t *buf = malloc(args->pagesize); - uint8_t *oob = malloc(args->oobsize); - uint8_t *calc_oob = malloc(args->oobsize); - uint8_t *calc_buf = malloc(args->pagesize); - uint8_t *page_buf; - int pages_per_block = args->blocksize / args->pagesize; - int badpos = args->bad_marker_offs_in_oob; - uint8_t ecc_code[3] = { 0, }; /* temp */ - uint8_t calc_ecc_code[3] = { 0, }; /* temp */ - - if (!buf || !oob || !calc_oob || !calc_buf) - exit(EXIT_FAILURE); - - while (!feof(in_fp)) { - /* read page by page */ - read = fread(buf, 1, args->pagesize, in_fp); - if (ferror(in_fp)) { - fprintf(stderr, "I/O Error."); - exit(EXIT_FAILURE); - } - if (read != (ssize_t)args->pagesize) - break; - - read = fread(oob, 1, args->oobsize, in_fp); - if (ferror(in_fp)) { - fprintf(stderr, "I/O Error."); - exit(EXIT_FAILURE); - } - - page_buf = buf; /* default is unmodified data */ - - if ((page == 0 || page == 1) && (oob[badpos] != 0xff)) { - if (verbose) - printf("Block %d is bad\n", - page / pages_per_block); - goto write_data; - } - if (args->correct_ecc) - page_buf = calc_buf; - - process_page(args, buf, calc_oob); - memcpy(calc_buf, buf, args->pagesize); - - if (verbose && oob_cmp(args->nand_oob, oob, calc_oob) != 0) { - printf("\nECC compare mismatch found at block %d page %d!\n", - page / pages_per_block, page % pages_per_block); - - printf("Read out OOB Data:\n"); - hexdump(stdout, oob, args->oobsize); - - printf("Calculated OOB Data:\n"); - hexdump(stdout, calc_oob, args->oobsize); - } - - /* Do correction on subpage base */ - for (i = 0, eccpoi = 0; i < args->pagesize; i += 256, eccpoi += 3) { - int j; - - for (j = 0; j < 3; j++) { - ecc_code[j] = oob[args->nand_oob->eccpos[eccpoi + j]]; - calc_ecc_code[j] = - calc_oob[args->nand_oob->eccpos[eccpoi + j]]; - } - rc = nand_correct_data(calc_buf + i, ecc_code, - calc_ecc_code); - if (rc == -1) - fprintf(stdout, "Uncorrectable ECC error at " - "block %d page %d/%d\n", - page / pages_per_block, - page % pages_per_block, i / 256); - else if (rc > 0) - fprintf(stdout, "Correctable ECC error at " - "block %d page %d/%d\n", - page / pages_per_block, - page % pages_per_block, i / 256); - } - - write_data: - rc = fwrite(page_buf, 1, args->pagesize, bin_fp); - if (ferror(bin_fp)) { - fprintf(stderr, "I/O Error."); - exit(EXIT_FAILURE); - } - rc = fwrite(oob, 1, args->oobsize, oob_fp); - if (ferror(bin_fp)) { - fprintf(stderr, "I/O Error."); - exit(EXIT_FAILURE); - } - - page++; - } - free(calc_buf); - free(calc_oob); - free(oob); - free(buf); - return 0; -} - -static int split_blocks(struct args *args, FILE *in_fp) -{ - uint8_t *buf; - int pages_per_block = args->blocksize / args->pagesize; - int block_len = pages_per_block * (args->pagesize + args->oobsize); - int blocks = args->in_len / block_len; - char bname[256] = { 0, }; - int badpos = args->bad_marker_offs_in_oob; - int bad_blocks = 0, i, bad_block = 0; - ssize_t rc; - FILE *b; - - buf = malloc(block_len); - if (!buf) { - perror("Not enough memory"); - exit(EXIT_FAILURE); - } - - for (i = 0; i < blocks; i++) { - rc = fread(buf, 1, block_len, in_fp); - if (rc != block_len) { - fprintf(stderr, "cannot read enough data!\n"); - exit(EXIT_FAILURE); - } - - /* do block analysis */ - bad_block = 0; - if ((buf[args->pagesize + badpos] != 0xff) || - (buf[2 * args->pagesize + args->oobsize + badpos] != 0xff)) { - bad_blocks++; - bad_block = 1; - } - if ((verbose && bad_block) || (verbose > 1)) { - printf("-- (block %d oob of page 0 and 1)\n", i); - hexdump(stdout, buf + args->pagesize, args->oobsize); - printf("--\n"); - hexdump(stdout, buf + 2 * args->pagesize + - args->oobsize, args->oobsize); - } - - /* write complete block out */ - snprintf(bname, sizeof(bname) - 1, "%s.%d", args->arg1, i); - b = fopen(bname, "w+"); - if (!b) { - perror("Cannot open file"); - exit(EXIT_FAILURE); - } - rc = fwrite(buf, 1, block_len, b); - if (rc != block_len) { - fprintf(stderr, "could not write all data!\n"); - exit(EXIT_FAILURE); - } - fclose(b); - } - - free(buf); - if (bad_blocks || verbose) - fprintf(stderr, "%d blocks, %d bad blocks\n", - blocks, bad_blocks); - return 0; -} - -int -main(int argc, char *argv[]) -{ - FILE *in, *bin = NULL, *oob = NULL; - struct stat file_info; - - parse_opt(argc, argv, &myargs); - - if (!myargs.arg1) { - fprintf(stderr, "Please specify input file!\n"); - exit(EXIT_FAILURE); - } - - if (lstat(myargs.arg1, &file_info) != 0) { - perror("Cannot fetch file size from input file.\n"); - exit(EXIT_FAILURE); - } - myargs.in_len = file_info.st_size; - - in = fopen(myargs.arg1, "r"); - if (!in) { - perror("Cannot open file"); - exit(EXIT_FAILURE); - } - - if (myargs.split_blocks) { - split_blocks(&myargs, in); - goto out; - } - - bin = fopen(myargs.output_file, "w+"); - if (!bin) { - perror("Cannot open file"); - exit(EXIT_FAILURE); - } - oob = fopen(myargs.oob_file, "w+"); - if (!oob) { - perror("Cannot open file"); - exit(EXIT_FAILURE); - } - decompose_image(&myargs, in, bin, oob); - - out: - if (in) fclose(in); - if (bin) fclose(bin); - if (oob) fclose(oob); - exit(EXIT_SUCCESS); -} diff --git a/ubi-utils/sort-me-out/nandcorr.c b/ubi-utils/sort-me-out/nandcorr.c deleted file mode 100644 index caa07e2..0000000 --- a/ubi-utils/sort-me-out/nandcorr.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * ECC algorithm for NAND FLASH. Detects and corrects 1 bit errors in - * a 256 bytes of data. - * - * Reimplement by Thomas Gleixner after staring long enough at the - * mess in drivers/mtd/nand/nandecc.c - * - */ - -#include "nandecc.h" - -static int countbits(uint32_t byte) -{ - int res = 0; - - for (;byte; byte >>= 1) - res += byte & 0x01; - return res; -} - -/** - * @dat: data which should be corrected - * @read_ecc: ecc information read from flash - * @calc_ecc: calculated ecc information from the data - * @return: number of corrected bytes - * or -1 when no correction is possible - */ -int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc, - const uint8_t *calc_ecc) -{ - uint8_t s0, s1, s2; - - /* - * Do error detection - * - * Be careful, the index magic is due to a pointer to a - * uint32_t. - */ - s0 = calc_ecc[0] ^ read_ecc[0]; - s1 = calc_ecc[1] ^ read_ecc[1]; - s2 = calc_ecc[2] ^ read_ecc[2]; - - if ((s0 | s1 | s2) == 0) - return 0; - - /* Check for a single bit error */ - if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 && - ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && - ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) { - - uint32_t byteoffs, bitnum; - - byteoffs = (s1 << 0) & 0x80; - byteoffs |= (s1 << 1) & 0x40; - byteoffs |= (s1 << 2) & 0x20; - byteoffs |= (s1 << 3) & 0x10; - - byteoffs |= (s0 >> 4) & 0x08; - byteoffs |= (s0 >> 3) & 0x04; - byteoffs |= (s0 >> 2) & 0x02; - byteoffs |= (s0 >> 1) & 0x01; - - bitnum = (s2 >> 5) & 0x04; - bitnum |= (s2 >> 4) & 0x02; - bitnum |= (s2 >> 3) & 0x01; - - dat[byteoffs] ^= (1 << bitnum); - - return 1; - } - - if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1) - return 1; - - return -1; -} - diff --git a/ubi-utils/sort-me-out/nandecc.c b/ubi-utils/sort-me-out/nandecc.c deleted file mode 100644 index 71660ef..0000000 --- a/ubi-utils/sort-me-out/nandecc.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * This file contains an ECC algorithm from Toshiba that detects and - * corrects 1 bit errors in a 256 byte block of data. - * - * drivers/mtd/nand/nand_ecc.c - * - * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) - * Toshiba America Electronics Components, Inc. - * - * This file is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 or (at your option) any - * later version. - * - * This file is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this file; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * As a special exception, if other files instantiate templates or use - * macros or inline functions from these files, or you compile these - * files and link them with other works to produce a work based on these - * files, these files do not by themselves cause the resulting work to be - * covered by the GNU General Public License. However the source code for - * these files must still be made available in accordance with section (3) - * of the GNU General Public License. - * - * This exception does not invalidate any other reasons why a work based on - * this file might be covered by the GNU General Public License. - */ - -#include "nandecc.h" - -/* - * Pre-calculated 256-way 1 byte column parity - */ -static const uint8_t nand_ecc_precalc_table[] = { - 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, - 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, - 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, - 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, - 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, - 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, - 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, - 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, - 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, - 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, - 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, - 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, - 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, - 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, - 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, - 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, - 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, - 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, - 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, - 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, - 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, - 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, - 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, - 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, - 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, - 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, - 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, - 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, - 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, - 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, - 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, - 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 -}; - -/** - * nand_trans_result - [GENERIC] create non-inverted ECC - * @reg2: line parity reg 2 - * @reg3: line parity reg 3 - * @ecc_code: ecc - * - * Creates non-inverted ECC code from line parity - */ -static void nand_trans_result(uint8_t reg2, uint8_t reg3, - uint8_t *ecc_code) -{ - uint8_t a, b, i, tmp1, tmp2; - - /* Initialize variables */ - a = b = 0x80; - tmp1 = tmp2 = 0; - - /* Calculate first ECC byte */ - for (i = 0; i < 4; i++) { - if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ - tmp1 |= b; - b >>= 1; - if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ - tmp1 |= b; - b >>= 1; - a >>= 1; - } - - /* Calculate second ECC byte */ - b = 0x80; - for (i = 0; i < 4; i++) { - if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ - tmp2 |= b; - b >>= 1; - if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ - tmp2 |= b; - b >>= 1; - a >>= 1; - } - - /* Store two of the ECC bytes */ - ecc_code[1] = tmp1; - ecc_code[0] = tmp2; -} - -/** - * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for - * 256 byte block - * - * @dat: raw data - * @ecc_code: buffer for ECC - */ -int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code) -{ - uint8_t idx, reg1, reg2, reg3; - int j; - - /* Initialize variables */ - reg1 = reg2 = reg3 = 0; - ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; - - /* Build up column parity */ - for(j = 0; j < 256; j++) { - - /* Get CP0 - CP5 from table */ - idx = nand_ecc_precalc_table[dat[j]]; - reg1 ^= (idx & 0x3f); - - /* All bit XOR = 1 ? */ - if (idx & 0x40) { - reg3 ^= (uint8_t) j; - reg2 ^= ~((uint8_t) j); - } - } - - /* Create non-inverted ECC code from line parity */ - nand_trans_result(reg2, reg3, ecc_code); - - /* Calculate final ECC code */ - ecc_code[0] = ~ecc_code[0]; - ecc_code[1] = ~ecc_code[1]; - ecc_code[2] = ((~reg1) << 2) | 0x03; - return 0; -} diff --git a/ubi-utils/sort-me-out/nandecc.h b/ubi-utils/sort-me-out/nandecc.h deleted file mode 100644 index bcf1982..0000000 --- a/ubi-utils/sort-me-out/nandecc.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _NAND_ECC_H -#define _NAND_ECC_H -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * NAND ecc functions - */ - -#include <stdint.h> - -int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code); -int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc, - const uint8_t *calc_ecc); - -#endif diff --git a/ubi-utils/sort-me-out/pdd.txt b/ubi-utils/sort-me-out/pdd.txt deleted file mode 100644 index a3ad915..0000000 --- a/ubi-utils/sort-me-out/pdd.txt +++ /dev/null @@ -1,16 +0,0 @@ -pdd=flash_type,flash_size,flash_eraseblock_size,flash_page_size,card_serialnumber,card_type,ethaddr,eth1addr,eth0,eth1,total,card_hardwarelevel -pdd_preserve=ethaddr,eth1addr,card_serialnumber -# To be personalized -ethaddr=00:04:34:56:78:9A -eth1addr=00:04:34:56:78:9B -card_serialnumber=SN0 -# Static for this card type -total=102M -card_type=nand_driven_testcard -card_hardwarelevel=0 -eth0=bcm5222,eth0,0 -eth1=bcm5222,eth0,1 -flash_type=NAND -flash_size=0x08000000 -flash_eraseblock_size=0x00020000 -flash_page_size=0x00000800 diff --git a/ubi-utils/sort-me-out/pddcustomize.c b/ubi-utils/sort-me-out/pddcustomize.c deleted file mode 100644 index 515efd6..0000000 --- a/ubi-utils/sort-me-out/pddcustomize.c +++ /dev/null @@ -1,509 +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 - * - * PDD (platform description data) contains a set of system specific - * boot-parameters. Some of those parameters need to be handled - * special on updates, e.g. the MAC addresses. They must also be kept - * if the system is updated and one must be able to modify them when - * the system has booted the first time. This tool is intended to do - * PDD modification. - * - * 1.3 Removed argp because we want to use uClibc. - * 1.4 Minor cleanups - * 1.5 Migrated to new libubi - */ - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> -#include <unistd.h> -#include <limits.h> -#include <errno.h> -#include <mtd/ubi-header.h> - -#include "config.h" -#include "bootenv.h" -#include "error.h" -#include "example_ubi.h" -#include "libubi.h" -#include "ubimirror.h" - -#define PROGRAM_VERSION "1.5" - -#define DEFAULT_DEV_PATTERN "/dev/ubi%d" -#define DEFAULT_VOL_PATTERN "/dev/ubi%d_%d" - -typedef enum action_t { - ACT_NORMAL = 0, - ACT_LIST, - ACT_ARGP_ABORT, - ACT_ARGP_ERR, -} action_t; - -#define ABORT_ARGP do { \ - args->action = ACT_ARGP_ABORT; \ -} while (0) - -#define ERR_ARGP do { \ - args->action = ACT_ARGP_ERR; \ -} while (0) - -static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" - "pddcustomize - customize bootenv and pdd values.\n"; - -static const char *optionsstr = -" -b, --both Mirror updated PDD to redundand copy.\n" -" -c, --copyright Print copyright information.\n" -" -i, --input=<input> Binary input file. For debug purposes.\n" -" -l, --list List card bootenv/pdd values.\n" -" -o, --output=<output> Binary output file. For debug purposes.\n" -" -s, --side=<seqnum> The side/seqnum to update.\n" -" -x, --host use x86 platform for debugging.\n" -" -?, --help Give this help list\n" -" --usage Give a short usage message\n" -" -V, --version Print program version\n"; - -static const char *usage = -"Usage: pddcustomize [-bclx?V] [-i <input>] [-o <output>] [-s <seqnum>]\n" -" [--both] [--copyright] [--input=<input>] [--list]\n" -" [--output=<output>] [--side=<seqnum>] [--host] [--help] [--usage]\n" -" [--version] [key=value] [...]\n"; - -struct option long_options[] = { - { .name = "both", .has_arg = 0, .flag = NULL, .val = 'b' }, - { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, - { .name = "input", .has_arg = 1, .flag = NULL, .val = 'i' }, - { .name = "list", .has_arg = 0, .flag = NULL, .val = 'l' }, - { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, - { .name = "side", .has_arg = 1, .flag = NULL, .val = 's' }, - { .name = "host", .has_arg = 0, .flag = NULL, .val = 'x' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, - { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0} -}; - -static const char copyright [] __attribute__((unused)) = - "Copyright IBM Corp 2006"; - -typedef struct myargs { - action_t action; - const char* file_in; - const char* file_out; - int both; - int side; - int x86; /* X86 host, use files for testing */ - bootenv_t env_in; - - char *arg1; - char **options; /* [STRING...] */ -} myargs; - -static int -get_update_side(const char* str) -{ - uint32_t i = strtoul(str, NULL, 0); - - if ((i != 0) && (i != 1)) { - return -1; - } - - return i; -} - -static int -extract_pair(bootenv_t env, const char* str) -{ - int rc = 0; - char* key; - char* val; - - key = strdup(str); - if (key == NULL) - return -ENOMEM; - - val = strstr(key, "="); - if (val == NULL) { - err_msg("Wrong argument: %s\n" - "Expecting key=value pair.\n", str); - rc = -1; - goto err; - } - - *val = '\0'; /* split strings */ - val++; - rc = bootenv_set(env, key, val); - -err: - free(key); - return rc; -} - -static int -parse_opt(int argc, char **argv, myargs *args) -{ - int rc = 0; - - while (1) { - int key; - - key = getopt_long(argc, argv, "clbxs:i:o:?V", - long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'c': - err_msg("%s\n", copyright); - ABORT_ARGP; - break; - case 'l': - args->action = ACT_LIST; - break; - case 'b': - args->both = 1; - break; - case 'x': - args->x86 = 1; - break; - case 's': - args->side = get_update_side(optarg); - if (args->side < 0) { - err_msg("Unsupported seqnum: %d.\n" - "Supported seqnums are " - "'0' and '1'\n", - args->side, optarg); - ERR_ARGP; - } - break; - case 'i': - args->file_in = optarg; - break; - case 'o': - args->file_out = optarg; - break; - case '?': /* help */ - err_msg("Usage: pddcustomize [OPTION...] " - "[key=value] [...]"); - err_msg("%s", doc); - err_msg("%s", optionsstr); - err_msg("\nReport bugs to %s", - PACKAGE_BUGREPORT); - exit(0); - break; - case 'V': - err_msg("%s", PROGRAM_VERSION); - exit(0); - break; - default: - err_msg("%s", usage); - exit(-1); - } - } - - if (optind < argc) { - rc = extract_pair(args->env_in, argv[optind++]); - if (rc != 0) - ERR_ARGP; - } - - return 0; -} - -static int -list_bootenv(bootenv_t env) -{ - int rc = 0; - rc = bootenv_write_txt(stdout, env); - if (rc != 0) { - err_msg("Cannot list bootenv/pdd. rc: %d\n", rc); - goto err; - } -err: - return rc; -} - -static int -process_key_value(bootenv_t env_in, bootenv_t env) -{ - int rc = 0; - size_t size, i; - const char* tmp; - const char** key_vec = NULL; - - rc = bootenv_get_key_vector(env_in, &size, 0, &key_vec); - if (rc != 0) - goto err; - - for (i = 0; i < size; i++) { - rc = bootenv_get(env_in, key_vec[i], &tmp); - if (rc != 0) { - err_msg("Cannot read value to input key: %s. rc: %d\n", - key_vec[i], rc); - goto err; - } - rc = bootenv_set(env, key_vec[i], tmp); - if (rc != 0) { - err_msg("Cannot set value key: %s. rc: %d\n", - key_vec[i], rc); - goto err; - } - } - -err: - if (key_vec != NULL) - free(key_vec); - return rc; -} - -static int -read_bootenv(const char* file, bootenv_t env) -{ - int rc = 0; - FILE* fp_in = NULL; - - fp_in = fopen(file, "rb"); - if (fp_in == NULL) { - err_msg("Cannot open file: %s\n", file); - return -EIO; - } - - rc = bootenv_read(fp_in, env, BOOTENV_MAXSIZE); - if (rc != 0) { - err_msg("Cannot read bootenv from file %s. rc: %d\n", - file, rc); - goto err; - } - -err: - fclose(fp_in); - return rc; -} - -/* - * Read bootenv from ubi volume - */ -static int -ubi_read_bootenv(uint32_t devno, uint32_t id, bootenv_t env) -{ - libubi_t ulib; - int rc = 0; - char path[PATH_MAX]; - FILE* fp_in = NULL; - - ulib = libubi_open(); - if (ulib == NULL) { - err_msg("Cannot allocate ubi structure\n"); - return -1; - } - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); - - fp_in = fopen(path, "r"); - if (fp_in == NULL) { - err_msg("Cannot open volume:%d number:%d\n", devno, id); - goto err; - } - - rc = bootenv_read(fp_in, env, BOOTENV_MAXSIZE); - if (rc != 0) { - err_msg("Cannot read volume:%d number:%d\n", devno, id); - goto err; - } - -err: - if (fp_in) - fclose(fp_in); - libubi_close(ulib); - return rc; -} - -static int -write_bootenv(const char* file, bootenv_t env) -{ - int rc = 0; - FILE* fp_out; - - fp_out = fopen(file, "wb"); - if (fp_out == NULL) { - err_msg("Cannot open file: %s\n", file); - return -EIO; - } - - rc = bootenv_write(fp_out, env); - if (rc != 0) { - err_msg("Cannot write bootenv to file %s. rc: %d\n", file, rc); - goto err; - } - -err: - fclose(fp_out); - return rc; -} - -/* - * Read bootenv from ubi volume - */ -static int -ubi_write_bootenv(uint32_t devno, uint32_t id, bootenv_t env) -{ - libubi_t ulib; - int rc = 0; - char path[PATH_MAX]; - FILE* fp_out = NULL; - size_t nbytes ; - - rc = bootenv_size(env, &nbytes); - if (rc) { - err_msg("Cannot determine size of bootenv structure\n"); - return rc; - } - ulib = libubi_open(); - if (ulib == NULL) { - err_msg("Cannot allocate ubi structure\n"); - return rc; - } - - snprintf(path, PATH_MAX, DEFAULT_VOL_PATTERN, devno, id); - - fp_out = fopen(path, "r+"); - if (fp_out == NULL) { - err_msg("Cannot fopen volume:%d number:%d\n", devno, id); - goto err; - } - - rc = bootenv_write(fp_out, env); - if (rc != 0) { - err_msg("Cannot write bootenv to volume %d number:%d\n", - devno, id); - goto err; - } - -err: - if( fp_out ) - fclose(fp_out); - libubi_close(ulib); - return rc; -} - -static int -do_mirror(int volno) -{ - char errbuf[1024]; - uint32_t ids[2]; - int rc; - int src_volno_idx = 0; - - ids[0] = EXAMPLE_BOOTENV_VOL_ID_1; - ids[1] = EXAMPLE_BOOTENV_VOL_ID_2; - - if (volno == EXAMPLE_BOOTENV_VOL_ID_2) - src_volno_idx = 1; - - rc = ubimirror(EXAMPLE_UBI_DEVICE, src_volno_idx, ids, 2, errbuf, - sizeof errbuf); - if( rc ) - err_msg(errbuf); - return rc; -} - -int -main(int argc, char **argv) { - int rc = 0; - bootenv_t env = NULL; - uint32_t boot_volno; - myargs args = { - .action = ACT_NORMAL, - .file_in = NULL, - .file_out = NULL, - .side = -1, - .x86 = 0, - .both = 0, - .env_in = NULL, - - .arg1 = NULL, - .options = NULL, - }; - - rc = bootenv_create(&env); - if (rc != 0) { - err_msg("Cannot create bootenv handle. rc: %d", rc); - goto err; - } - - rc = bootenv_create(&(args.env_in)); - if (rc != 0) { - err_msg("Cannot create bootenv handle. rc: %d", rc); - goto err; - } - - parse_opt(argc, argv, &args); - if (args.action == ACT_ARGP_ERR) { - rc = -1; - goto err; - } - if (args.action == ACT_ARGP_ABORT) { - rc = 0; - goto out; - } - - if ((args.side == 0) || (args.side == -1)) - boot_volno = EXAMPLE_BOOTENV_VOL_ID_1; - else - boot_volno = EXAMPLE_BOOTENV_VOL_ID_2; - - if( args.x86 ) - rc = read_bootenv(args.file_in, env); - else - rc = ubi_read_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env); - if (rc != 0) { - goto err; - } - - if (args.action == ACT_LIST) { - rc = list_bootenv(env); - if (rc != 0) { - goto err; - } - goto out; - } - - rc = process_key_value(args.env_in, env); - if (rc != 0) { - goto err; - } - - if( args.x86 ) - rc = write_bootenv(args.file_in, env); - else - rc = ubi_write_bootenv(EXAMPLE_UBI_DEVICE, boot_volno, env); - if (rc != 0) { - goto err; - } - if( args.both ) /* No side specified, update both */ - rc = do_mirror(boot_volno); - - out: - err: - bootenv_destroy(&env); - bootenv_destroy(&(args.env_in)); - return rc; -} diff --git a/ubi-utils/sort-me-out/peb.c b/ubi-utils/sort-me-out/peb.c deleted file mode 100644 index 160a463..0000000 --- a/ubi-utils/sort-me-out/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/sort-me-out/peb.h b/ubi-utils/sort-me-out/peb.h deleted file mode 100644 index 246bce8..0000000 --- a/ubi-utils/sort-me-out/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/sort-me-out/pfi.c b/ubi-utils/sort-me-out/pfi.c deleted file mode 100644 index fa835e2..0000000 --- a/ubi-utils/sort-me-out/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/sort-me-out/pfi.h b/ubi-utils/sort-me-out/pfi.h deleted file mode 100644 index 8c5cc07..0000000 --- a/ubi-utils/sort-me-out/pfi.h +++ /dev/null @@ -1,244 +0,0 @@ -#ifndef __pfi_h -#define __pfi_h -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * @file pfi.h - * - * @author Oliver Lohmann <oliloh@de.ibm.com> - * Andreas Arnez <arnez@de.ibm.com> - * Joern Engel <engeljoe@de.ibm.com> - * Frank Haverkamp <haverkam@de.ibm.com> - * - * @brief libpfi will hold all code to create and process pfi - * images. Definitions made in this file are equaly usable for the - * development host and the target system. - * - * @note This header additionally holds the official definitions for - * the pfi headers. - */ - -#include <stdio.h> /* FILE */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Definitions. */ - -#define PFI_HDRVERSION 1 /* current header version */ - -#define PFI_ENOVERSION 1 /* unknown version */ -#define PFI_ENOHEADER 2 /* not a pfi header */ -#define PFI_EINSUFF 3 /* insufficient information */ -#define PFI_EUNDEF 4 /* key not defined */ -#define PFI_ENOMEM 5 /* out of memory */ -#define PFI_EBADTYPE 6 /* bad data type */ -#define PFI_EFILE 7 /* file I/O error: see errno */ -#define PFI_EFILEINVAL 8 /* file format not valid */ -#define PFI_EINVAL 9 /* invalid parameter */ -#define PFI_ERANGE 10 /* invalid range */ -#define PFI_EMODE 11 /* expecting other mode in this header */ -#define PFI_DATA_START 12 /* data section starts */ -#define PFI_EMAX 13 /* should be always larger as the largest - error code */ - -#define PFI_LABEL_LEN 64 /* This is the maximum length for a - PFI header label */ -#define PFI_KEYWORD_LEN 32 /* This is the maximum length for an - entry in the mode and type fields */ - -#define PFI_UBI_MAX_VOLUMES 128 -#define PFI_UBI_VOL_NAME_LEN 127 - -/** - * @brief The pfi header allows to set flags which influence the flashing - * behaviour. - */ -#define PFI_FLAG_PROTECTED 0x00000001 - - -/** - * @brief Handle to pfi header. Used in most of the functions associated - * with pfi file handling. - */ -typedef struct pfi_header *pfi_header; - - -/** - * @brief Initialize a pfi header object. - * - * @param head Pointer to handle. This function allocates memory - * for this data structure. - * @return 0 on success, otherwise: - * PFI_ENOMEM : no memory available for the handle. - */ -int pfi_header_init (pfi_header *head); - - -/** - * @brief Destroy a pfi header object. - * - * @param head handle. head is invalid after calling this function. - * @return 0 always. - */ -int pfi_header_destroy (pfi_header *head); - - -/** - * @brief Add a key/value pair to a pfi header object. - * - * @param head handle. - * @param key pointer to key string. Must be 0 terminated. - * @param value pointer to value string. Must be 0 terminated. - * @return 0 on success, otherwise: - * PFI_EUNDEF : key was not found. - * PFI_ENOMEM : no memory available for the handle. - * PFI_EBADTYPE : value is not an hex string. This happens - * when the key stores an integer and the - * new value is not convertable e.g. not in - * 0xXXXXXXXX format. - */ -int pfi_header_setvalue (pfi_header head, - const char *key, const char *value); - - -/** - * @brief Add a key/value pair to a pfi header object. Provide the - * value as a number. - * - * @param head handle. - * @param key pointer to key string. Must be 0 terminated. - * @param value value to set. - * @return 0 on success, otherwise: - * PFI_EUNDEF : key was not found. - * PFI_EBADTYPE : value is not a string. This happens - * when the key stores a string. - */ -int pfi_header_setnumber (pfi_header head, - const char *key, uint32_t value); - - -/** - * @brief For a given key, return the numerical value stored in a - * pfi header object. - * - * @param head handle. - * @param key pointer to key string. Must be 0 terminated. - * @param value pointer to value. - * @return 0 on success, otherwise: - * PFI_EUNDEF : key was not found. - * PFI_EBADTYPE : stored value is not an integer but a string. - */ -int pfi_header_getnumber (pfi_header head, - const char *key, uint32_t *value); - - -static inline uint32_t -pfi_getnumber(pfi_header head, const char *key) -{ - uint32_t value; - pfi_header_getnumber(head, key, &value); - return value; -} - -/** - * @brief For a given key, return the string value stored in a pfi - * header object. - * - * @param head handle. - * @param key pointer to key string. Must be 0 terminated. - * @param value pointer to value string. Memory must be allocated by the user. - * @return 0 on success, otherwise: - * PFI_EUNDEF : key was not found. - * PFI_EBADTYPE : stored value is not a string but an integer. - */ -int pfi_header_getstring (pfi_header head, - const char *key, char *value, size_t size); - - -/** - * @brief Write a pfi header object into a given file. - * - * @param out output stream. - * @param head handle. - * @return 0 on success, error values otherwise: - * PFI_EINSUFF : not all mandatory fields are filled. - * PFI_ENOHEADER : wrong header version or magic number. - * -E* : see <asm/errno.h>. - */ -int pfi_header_write (FILE *out, pfi_header head); - - -/** - * @brief Read a pfi header object from a given file. - * - * @param in input stream. - * @param head handle. - * @return 0 on success, error values otherwise: - * PFI_ENOVERSION: unknown header version. - * PFI_EFILE : cannot read enough data. - * PFI_ENOHEADER : wrong header version or magic number. - * -E* : see <asm/errno.h>. - * - * If the header verification returned success the user can assume that - * all mandatory fields for a particular version are accessible. Checking - * the return code when calling the get-function for those keys is not - * required in those cases. For optional fields the checking must still be - * done. - */ -int pfi_header_read (FILE *in, pfi_header head); - - -/** - * @brief Display a pfi header in human-readable form. - * - * @param out output stream. - * @param head handle. - * @return always 0. - * - * @note Prints out that it is not implemented and whom you should - * contact if you need it urgently!. - */ -int pfi_header_dump (FILE *out, pfi_header head); - - -/* - * @brief Iterates over a stream of pfi files. The iterator function - * must advance the file pointer in FILE *in to the next pfi - * header. Function exists on feof(in). - * - * @param in input file descriptor, must be open and valid. - * @param func iterator function called when pfi header could be - * read and was validated. The function must return 0 on - * success. - * @return See pfi_header_init and pfi_header_read. - * PFI_EINVAL : func is not valid - * 0 ok. - */ -typedef int (* pfi_read_func)(FILE *in, pfi_header hdr, void *priv_data); - -int pfi_read (FILE *in, pfi_read_func func, void *priv_data); - - -#ifdef __cplusplus -} -#endif - -#endif /* __pfi_h */ diff --git a/ubi-utils/sort-me-out/pfi2bin.c b/ubi-utils/sort-me-out/pfi2bin.c deleted file mode 100644 index 7f31938..0000000 --- a/ubi-utils/sort-me-out/pfi2bin.c +++ /dev/null @@ -1,681 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - * - * Convert a PFI file (partial flash image) into a plain binary file. - * This tool can be used to prepare the data to be burned into flash - * chips in a manufacturing step where the flashes are written before - * being soldered onto the hardware. For NAND images another step is - * required to add the right OOB data to the binary image. - * - * 1.3 Removed argp because we want to use uClibc. - * 1.4 Minor cleanups - */ - -#include <stdlib.h> -#include <stdint.h> -#include <getopt.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <errno.h> - -#include <ubigen.h> -#include <mtd/ubi-header.h> - -#include "config.h" -#include "list.h" -#include "error.h" -#include "reader.h" -#include "peb.h" -#include "crc32.h" - -#define PROGRAM_VERSION "1.4" - -#define MAX_FNAME 255 -#define DEFAULT_ERASE_COUNT 0 /* Hmmm.... Perhaps */ -#define ERR_BUF_SIZE 1024 - -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -static uint32_t crc32_table[256]; -static char err_buf[ERR_BUF_SIZE]; - -/* - * Data used to buffer raw blocks which have to be - * located at a specific point inside the generated RAW file - */ - -typedef enum action_t { - ACT_NOTHING = 0x00000000, - ACT_RAW = 0x00000001, -} action_t; - -static const char copyright [] __attribute__((unused)) = - "(c) Copyright IBM Corp 2006\n"; - -static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" - "pfi2bin - a tool to convert PFI files into binary images.\n"; - -static const char *optionsstr = -" Common settings:\n" -" -c, --copyright\n" -" -v, --verbose Print more information.\n" -"\n" -" Input:\n" -" -j, --platform=pdd-file PDD information which contains the card settings.\n" -"\n" -" Output:\n" -" -o, --output=filename Outputfile, default: stdout.\n" -"\n" -" -?, --help Give this help list\n" -" --usage Give a short usage message\n" -" -V, --version Print program version\n"; - -static const char *usage = -"Usage: pfi2bin [-cv?V] [-j pdd-file] [-o filename] [--copyright]\n" -" [--verbose] [--platform=pdd-file] [--output=filename] [--help]\n" -" [--usage] [--version] pfifile\n"; - -struct option long_options[] = { - { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, - { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, - { .name = "platform", .has_arg = 1, .flag = NULL, .val = 'j' }, - { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, - { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0} -}; - -typedef struct io { - FILE* fp_pdd; /* a FilePointer to the PDD data */ - FILE* fp_pfi; /* a FilePointer to the PFI input stream */ - FILE* fp_out; /* a FilePointer to the output stream */ -} *io_t; - -typedef struct myargs { - /* common settings */ - action_t action; - int verbose; - const char *f_in_pfi; - const char *f_in_pdd; - const char *f_out; - - /* special stuff needed to get additional arguments */ - char *arg1; - char **options; /* [STRING...] */ -} myargs; - -static int -parse_opt(int argc, char **argv, myargs *args) -{ - while (1) { - int key; - - key = getopt_long(argc, argv, "cvj:o:?V", long_options, NULL); - if (key == -1) - break; - - switch (key) { - /* common settings */ - case 'v': /* --verbose=<level> */ - args->verbose = 1; - break; - - case 'c': /* --copyright */ - fprintf(stderr, "%s\n", copyright); - exit(0); - break; - - case 'j': /* --platform */ - args->f_in_pdd = optarg; - break; - - case 'o': /* --output */ - args->f_out = optarg; - break; - - case '?': /* help */ - printf("pfi2bin [OPTION...] pfifile\n"); - printf("%s", doc); - printf("%s", optionsstr); - printf("\nReport bugs to %s\n", - PACKAGE_BUGREPORT); - exit(0); - break; - - case 'V': - printf("%s\n", PROGRAM_VERSION); - exit(0); - break; - - default: - printf("%s", usage); - exit(-1); - } - } - - if (optind < argc) - args->f_in_pfi = argv[optind++]; - - return 0; -} - - -static size_t -byte_to_blk(size_t byte, size_t blk_size) -{ - return (byte % blk_size) == 0 - ? byte / blk_size - : byte / blk_size + 1; -} - - - - -/** - * @precondition IO: File stream points to first byte of RAW data. - * @postcondition IO: File stream points to first byte of next - * or EOF. - */ -static int -memorize_raw_eb(pfi_raw_t pfi_raw, pdd_data_t pdd, list_t *raw_pebs, - io_t io) -{ - int rc = 0; - uint32_t i; - - size_t read, to_read, eb_num; - size_t bytes_left; - list_t pebs = *raw_pebs; - peb_t peb = NULL; - - long old_file_pos = ftell(io->fp_pfi); - for (i = 0; i < pfi_raw->starts_size; i++) { - bytes_left = pfi_raw->data_size; - rc = fseek(io->fp_pfi, old_file_pos, SEEK_SET); - if (rc != 0) - goto err; - - eb_num = byte_to_blk(pfi_raw->starts[i], pdd->eb_size); - while (bytes_left) { - to_read = MIN(bytes_left, pdd->eb_size); - rc = peb_new(eb_num++, pdd->eb_size, &peb); - if (rc != 0) - goto err; - read = fread(peb->data, 1, to_read, io->fp_pfi); - if (read != to_read) { - rc = -EIO; - goto err; - } - pebs = append_elem(peb, pebs); - bytes_left -= read; - } - - } - *raw_pebs = pebs; - return 0; -err: - pebs = remove_all((free_func_t)&peb_free, pebs); - return rc; -} - -static int -convert_ubi_volume(pfi_ubi_t ubi, pdd_data_t pdd, list_t raw_pebs, - struct ubi_vtbl_record *vol_tab, - size_t *ebs_written, io_t io) -{ - int rc = 0; - uint32_t i, j; - peb_t raw_peb; - peb_t cmp_peb; - ubi_info_t u; - size_t leb_total = 0; - uint8_t vol_type; - - switch (ubi->type) { - case pfi_ubi_static: - vol_type = UBI_VID_STATIC; break; - case pfi_ubi_dynamic: - vol_type = UBI_VID_DYNAMIC; break; - default: - vol_type = UBI_VID_DYNAMIC; - } - - rc = peb_new(0, 0, &cmp_peb); - if (rc != 0) - goto err; - - long old_file_pos = ftell(io->fp_pfi); - for (i = 0; i < ubi->ids_size; i++) { - rc = fseek(io->fp_pfi, old_file_pos, SEEK_SET); - if (rc != 0) - goto err; - rc = ubigen_create(&u, ubi->ids[i], vol_type, - pdd->eb_size, DEFAULT_ERASE_COUNT, - ubi->alignment, UBI_VERSION, - pdd->vid_hdr_offset, 0, ubi->data_size, - io->fp_pfi, io->fp_out); - if (rc != 0) - goto err; - - rc = ubigen_get_leb_total(u, &leb_total); - if (rc != 0) - goto err; - - j = 0; - while(j < leb_total) { - cmp_peb->num = *ebs_written; - raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb, - raw_pebs); - if (raw_peb) { - rc = peb_write(io->fp_out, raw_peb); - } - else { - rc = ubigen_write_leb(u, NO_ERROR); - j++; - } - if (rc != 0) - goto err; - (*ebs_written)++; - } - /* memorize volume table entry */ - rc = ubigen_set_lvol_rec(u, ubi->size, - ubi->names[i], - (void*) &vol_tab[ubi->ids[i]]); - if (rc != 0) - goto err; - ubigen_destroy(&u); - } - - peb_free(&cmp_peb); - return 0; - -err: - peb_free(&cmp_peb); - ubigen_destroy(&u); - return rc; -} - - -static FILE* -my_fmemopen (void *buf, size_t size, const char *opentype) -{ - FILE* f; - size_t ret; - - assert(strcmp(opentype, "r") == 0); - - f = tmpfile(); - ret = fwrite(buf, 1, size, f); - rewind(f); - - return f; -} - -/** - * @brief Builds a UBI volume table from a volume entry list. - * @return 0 On success. - * else Error. - */ -static int -write_ubi_volume_table(pdd_data_t pdd, list_t raw_pebs, - struct ubi_vtbl_record *vol_tab, size_t vol_tab_size, - size_t *ebs_written, io_t io) -{ - int rc = 0; - ubi_info_t u; - peb_t raw_peb; - peb_t cmp_peb; - size_t leb_size, leb_total, j = 0; - uint8_t *ptr = NULL; - FILE* fp_leb = NULL; - int vt_slots; - size_t vol_tab_size_limit; - - rc = peb_new(0, 0, &cmp_peb); - if (rc != 0) - goto err; - - /* @FIXME: Artem creates one volume with 2 LEBs. - * IMO 2 volumes would be more convenient. In order - * to get 2 reserved LEBs from ubigen, I have to - * introduce this stupid mechanism. Until no final - * decision of the VTAB structure is made... Good enough. - */ - rc = ubigen_create(&u, UBI_LAYOUT_VOL_ID, UBI_VID_DYNAMIC, - pdd->eb_size, DEFAULT_ERASE_COUNT, - 1, UBI_VERSION, - pdd->vid_hdr_offset, UBI_COMPAT_REJECT, - vol_tab_size, stdin, io->fp_out); - /* @FIXME stdin for fp_in is a hack */ - if (rc != 0) - goto err; - rc = ubigen_get_leb_size(u, &leb_size); - if (rc != 0) - goto err; - ubigen_destroy(&u); - - /* - * The number of supported volumes is restricted by the eraseblock size - * and by the UBI_MAX_VOLUMES constant. - */ - vt_slots = leb_size / UBI_VTBL_RECORD_SIZE; - if (vt_slots > UBI_MAX_VOLUMES) - vt_slots = UBI_MAX_VOLUMES; - vol_tab_size_limit = vt_slots * UBI_VTBL_RECORD_SIZE; - - ptr = (uint8_t*) malloc(leb_size * sizeof(uint8_t)); - if (ptr == NULL) - goto err; - - memset(ptr, 0xff, leb_size); - memcpy(ptr, vol_tab, vol_tab_size_limit); - fp_leb = my_fmemopen(ptr, leb_size, "r"); - - rc = ubigen_create(&u, UBI_LAYOUT_VOL_ID, UBI_VID_DYNAMIC, - pdd->eb_size, DEFAULT_ERASE_COUNT, - 1, UBI_VERSION, pdd->vid_hdr_offset, - UBI_COMPAT_REJECT, leb_size * UBI_LAYOUT_VOLUME_EBS, - fp_leb, io->fp_out); - if (rc != 0) - goto err; - rc = ubigen_get_leb_total(u, &leb_total); - if (rc != 0) - goto err; - - long old_file_pos = ftell(fp_leb); - while(j < leb_total) { - rc = fseek(fp_leb, old_file_pos, SEEK_SET); - if (rc != 0) - goto err; - - cmp_peb->num = *ebs_written; - raw_peb = is_in((cmp_func_t)peb_cmp, cmp_peb, - raw_pebs); - if (raw_peb) { - rc = peb_write(io->fp_out, raw_peb); - } - else { - rc = ubigen_write_leb(u, NO_ERROR); - j++; - } - - if (rc != 0) - goto err; - (*ebs_written)++; - } - -err: - free(ptr); - peb_free(&cmp_peb); - ubigen_destroy(&u); - fclose(fp_leb); - return rc; -} - -static int -write_remaining_raw_ebs(pdd_data_t pdd, list_t raw_blocks, size_t *ebs_written, - FILE* fp_out) -{ - int rc = 0; - uint32_t j, delta; - list_t ptr; - peb_t empty_eb, peb; - - /* create an empty 0xff EB (for padding) */ - rc = peb_new(0, pdd->eb_size, &empty_eb); - - foreach(peb, ptr, raw_blocks) { - if (peb->num < *ebs_written) { - continue; /* omit blocks which - are already passed */ - } - - if (peb->num < *ebs_written) { - err_msg("eb_num: %d\n", peb->num); - err_msg("Bug: This should never happen. %d %s", - __LINE__, __FILE__); - goto err; - } - - delta = peb->num - *ebs_written; - if (((delta + *ebs_written) * pdd->eb_size) > pdd->flash_size) { - err_msg("RAW block outside of flash_size."); - goto err; - } - for (j = 0; j < delta; j++) { - rc = peb_write(fp_out, empty_eb); - if (rc != 0) - goto err; - (*ebs_written)++; - } - rc = peb_write(fp_out, peb); - if (rc != 0) - goto err; - (*ebs_written)++; - } - -err: - peb_free(&empty_eb); - return rc; -} - -static int -init_vol_tab(struct ubi_vtbl_record **vol_tab, size_t *vol_tab_size) -{ - uint32_t crc; - size_t i; - struct ubi_vtbl_record* res = NULL; - - *vol_tab_size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE; - - res = (struct ubi_vtbl_record*) calloc(1, *vol_tab_size); - if (vol_tab == NULL) { - return -ENOMEM; - } - - for (i = 0; i < UBI_MAX_VOLUMES; i++) { - crc = clc_crc32(crc32_table, UBI_CRC32_INIT, - &(res[i]), UBI_VTBL_RECORD_SIZE_CRC); - res[i].crc = __cpu_to_be32(crc); - } - - *vol_tab = res; - return 0; -} - -static int -create_raw(io_t io) -{ - int rc = 0; - size_t ebs_written = 0; /* eraseblocks written already... */ - size_t vol_tab_size; - list_t ptr; - - list_t pfi_raws = mk_empty(); /* list of raw sections from a pfi */ - list_t pfi_ubis = mk_empty(); /* list of ubi sections from a pfi */ - list_t raw_pebs = mk_empty(); /* list of raw eraseblocks */ - - struct ubi_vtbl_record *vol_tab = NULL; - pdd_data_t pdd = NULL; - - rc = init_vol_tab (&vol_tab, &vol_tab_size); - if (rc != 0) { - err_msg("Cannot initialize volume table."); - goto err; - } - - rc = read_pdd_data(io->fp_pdd, &pdd, - err_buf, ERR_BUF_SIZE); - if (rc != 0) { - err_msg("Cannot read necessary pdd_data: %s rc: %d", - err_buf, rc); - goto err; - } - - rc = read_pfi_headers(&pfi_raws, &pfi_ubis, io->fp_pfi, - err_buf, ERR_BUF_SIZE); - if (rc != 0) { - err_msg("Cannot read pfi header: %s rc: %d", - err_buf, rc); - goto err; - } - - pfi_raw_t pfi_raw; - foreach(pfi_raw, ptr, pfi_raws) { - rc = memorize_raw_eb(pfi_raw, pdd, &raw_pebs, - io); - if (rc != 0) { - err_msg("Cannot create raw_block in mem. rc: %d\n", - rc); - goto err; - } - } - - pfi_ubi_t pfi_ubi; - foreach(pfi_ubi, ptr, pfi_ubis) { - rc = convert_ubi_volume(pfi_ubi, pdd, raw_pebs, - vol_tab, &ebs_written, io); - if (rc != 0) { - err_msg("Cannot convert UBI volume. rc: %d\n", rc); - goto err; - } - } - - rc = write_ubi_volume_table(pdd, raw_pebs, vol_tab, vol_tab_size, - &ebs_written, io); - if (rc != 0) { - err_msg("Cannot write UBI volume table. rc: %d\n", rc); - goto err; - } - - rc = write_remaining_raw_ebs(pdd, raw_pebs, &ebs_written, io->fp_out); - if (rc != 0) - goto err; - - if (io->fp_out != stdout) - info_msg("Physical eraseblocks written: %8d\n", ebs_written); -err: - free(vol_tab); - pfi_raws = remove_all((free_func_t)&free_pfi_raw, pfi_raws); - pfi_ubis = remove_all((free_func_t)&free_pfi_ubi, pfi_ubis); - raw_pebs = remove_all((free_func_t)&peb_free, raw_pebs); - free_pdd_data(&pdd); - return rc; -} - - -/* ------------------------------------------------------------------------- */ -static void -open_io_handle(myargs *args, io_t io) -{ - /* set PDD input */ - io->fp_pdd = fopen(args->f_in_pdd, "r"); - if (io->fp_pdd == NULL) { - err_sys("Cannot open: %s", args->f_in_pdd); - } - - /* set PFI input */ - io->fp_pfi = fopen(args->f_in_pfi, "r"); - if (io->fp_pfi == NULL) { - err_sys("Cannot open PFI input file: %s", args->f_in_pfi); - } - - /* set output prefix */ - if (strcmp(args->f_out,"") == 0) - io->fp_out = stdout; - else { - io->fp_out = fopen(args->f_out, "wb"); - if (io->fp_out == NULL) { - err_sys("Cannot open output file: %s", args->f_out); - } - } -} - -static void -close_io_handle(io_t io) -{ - if (fclose(io->fp_pdd) != 0) { - err_sys("Cannot close PDD file."); - } - if (fclose(io->fp_pfi) != 0) { - err_sys("Cannot close PFI file."); - } - if (io->fp_out != stdout) { - if (fclose(io->fp_out) != 0) { - err_sys("Cannot close output file."); - } - } - - io->fp_pdd = NULL; - io->fp_pfi = NULL; - io->fp_out = NULL; -} - -int -main(int argc, char *argv[]) -{ - int rc = 0; - - ubigen_init(); - init_crc32_table(crc32_table); - - struct io io = {NULL, NULL, NULL}; - myargs args = { - .action = ACT_RAW, - .verbose = 0, - - .f_in_pfi = "", - .f_in_pdd = "", - .f_out = "", - - /* arguments */ - .arg1 = NULL, - .options = NULL, - }; - - /* parse arguments */ - parse_opt(argc, argv, &args); - - if (strcmp(args.f_in_pfi, "") == 0) { - err_quit("No PFI input file specified!"); - } - - if (strcmp(args.f_in_pdd, "") == 0) { - err_quit("No PDD input file specified!"); - } - - open_io_handle(&args, &io); - - info_msg("[ Creating RAW..."); - rc = create_raw(&io); - if (rc != 0) { - err_msg("Creating RAW failed."); - goto err; - } - -err: - close_io_handle(&io); - if (rc != 0) { - remove(args.f_out); - } - - return rc; -} diff --git a/ubi-utils/sort-me-out/pfiflash.c b/ubi-utils/sort-me-out/pfiflash.c deleted file mode 100644 index 754fe33..0000000 --- a/ubi-utils/sort-me-out/pfiflash.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - * Frank Haverkamp - * - * Process a PFI (partial flash image) and write the data to the - * specified UBI volumes. This tool is intended to be used for system - * update using PFI files. - * - * 1.1 fixed output to stderr and stdout in logfile mode. - * 1.2 updated. - * 1.3 removed argp parsing to be able to use uClib. - * 1.4 Minor cleanups. - * 1.5 Forgot to delete raw block before updating it. - * 1.6 Migrated to new libubi. - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> -#include <unistd.h> -#include <errno.h> - -#include <pfiflash.h> -#undef DEBUG -#include "error.h" -#include "config.h" - -#define PROGRAM_VERSION "1.6" - -static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" - "pfiflash - a tool for updating a controller with PFI files.\n"; - -static const char *optionsstr = -" Standard options:\n" -" -c, --copyright Print copyright information.\n" -" -l, --logfile=<file> Write a logfile to <file>.\n" -" -v, --verbose Be verbose during program execution.\n" -"\n" -" Process options:\n" -" -C, --complete Execute a complete system update. Updates both\n" -" sides.\n" -" -p, --pdd-update=<type> Specify the pdd-update algorithm. <type> is either\n" -" 'keep', 'merge' or 'overwrite'.\n" -" -r, --raw-flash=<dev> Flash the raw data. Use the specified mtd device.\n" -" -s, --side=<seqnum> Select the side which shall be updated.\n" -" -x, --compare Only compare on-flash and pfi data, print info if\n" -" an update is neccessary and return appropriate\n" -" error code.\n" -"\n" -" -?, --help Give this help list\n" -" --usage Give a short usage message\n" -" -V, --version Print program version\n"; - -static const char *usage = -"Usage: pfiflash [-cvC?V] [-l <file>] [-p <type>] [-r <dev>] [-s <seqnum>]\n" -" [--copyright] [--logfile=<file>] [--verbose] [--complete]\n" -" [--pdd-update=<type>] [--raw-flash=<dev>] [--side=<seqnum>]\n" -" [--compare] [--help] [--usage] [--version] [pfifile]\n"; - -static const char copyright [] __attribute__((unused)) = - "Copyright IBM Corp 2006"; - -struct option long_options[] = { - { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, - { .name = "logfile", .has_arg = 1, .flag = NULL, .val = 'l' }, - { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, - { .name = "complete", .has_arg = 0, .flag = NULL, .val = 'C' }, - { .name = "pdd-update", .has_arg = 1, .flag = NULL, .val = 'p' }, - { .name = "raw-flash", .has_arg = 1, .flag = NULL, .val = 'r' }, - { .name = "side", .has_arg = 1, .flag = NULL, .val = 's' }, - { .name = "compare", .has_arg = 0, .flag = NULL, .val = 'x' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, - { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0} -}; - -typedef struct myargs { - int verbose; - const char *logfile; - const char *raw_dev; - - pdd_handling_t pdd_handling; - int seqnum; - int compare; - int complete; - - FILE* fp_in; - - /* special stuff needed to get additional arguments */ - char *arg1; - char **options; /* [STRING...] */ -} myargs; - -static pdd_handling_t -get_pdd_handling(const char* str) -{ - if (strcmp(str, "keep") == 0) { - return PDD_KEEP; - } - if (strcmp(str, "merge") == 0) { - return PDD_MERGE; - } - if (strcmp(str, "overwrite") == 0) { - return PDD_OVERWRITE; - } - - return -1; -} - -static int -get_update_seqnum(const char* str) -{ - uint32_t i = strtoul(str, NULL, 0); - - if ((i != 0) && (i != 1)) { - return -1; - } - - return i; -} - - -static int -parse_opt(int argc, char **argv, myargs *args) -{ - while (1) { - int key; - - key = getopt_long(argc, argv, "cl:vCp:r:s:x?V", - long_options, NULL); - if (key == -1) - break; - - switch (key) { - /* standard options */ - case 'c': - err_msg("%s\n", copyright); - exit(0); - break; - case 'v': - args->verbose = 1; - break; - case 'l': - args->logfile = optarg; - break; - /* process options */ - case 'C': - args->complete = 1; - break; - case 'p': - args->pdd_handling = get_pdd_handling(optarg); - if ((int)args->pdd_handling < 0) { - err_quit("Unknown PDD handling: %s.\n" - "Please use either " - "'keep', 'merge' or" - "'overwrite'.\n'"); - } - break; - case 's': - args->seqnum = get_update_seqnum(optarg); - if (args->seqnum < 0) { - err_quit("Unsupported side: %s.\n" - "Supported sides are '0' " - "and '1'\n", optarg); - } - break; - case 'x': - args->compare = 1; - break; - case 'r': - args->raw_dev = optarg; - break; - case '?': /* help */ - err_msg("Usage: pfiflash [OPTION...] [pfifile]"); - err_msg("%s", doc); - err_msg("%s", optionsstr); - err_msg("\nReport bugs to %s\n", - PACKAGE_BUGREPORT); - exit(0); - break; - case 'V': - err_msg("%s", PROGRAM_VERSION); - exit(0); - break; - default: - err_msg("%s", usage); - exit(-1); - - } - } - - if (optind < argc) { - args->fp_in = fopen(argv[optind++], "r"); - if ((args->fp_in) == NULL) { - err_sys("Cannot open PFI file %s for input", - argv[optind]); - } - } - - return 0; -} - -int main (int argc, char** argv) -{ - int rc = 0; - char err_buf[PFIFLASH_MAX_ERR_BUF_SIZE]; - memset(err_buf, '\0', PFIFLASH_MAX_ERR_BUF_SIZE); - - myargs args = { - .verbose = 0, - .seqnum = -1, - .compare = 0, - .complete = 0, - .logfile = NULL, /* "/tmp/pfiflash.log", */ - .pdd_handling = PDD_KEEP, - .fp_in = stdin, - .raw_dev = NULL, - }; - - parse_opt(argc, argv, &args); - error_initlog(args.logfile); - - if (!args.fp_in) { - rc = -1; - snprintf(err_buf, PFIFLASH_MAX_ERR_BUF_SIZE, - "No PFI input file specified!\n"); - goto err; - } - - rc = pfiflash_with_options(args.fp_in, args.complete, args.seqnum, - args.compare, args.pdd_handling, args.raw_dev, err_buf, - PFIFLASH_MAX_ERR_BUF_SIZE); - if (rc < 0) { - goto err_fp; - } - - err_fp: - if (args.fp_in != stdin) - fclose(args.fp_in); - err: - if (rc != 0) - err_msg("pfiflash: %s\nrc: %d\n", err_buf, rc); - return rc; -} diff --git a/ubi-utils/sort-me-out/pfiflash.h b/ubi-utils/sort-me-out/pfiflash.h deleted file mode 100644 index 039705d..0000000 --- a/ubi-utils/sort-me-out/pfiflash.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef __PFIFLASH_H__ -#define __PFIFLASH_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * - * @file pfi.h - * - * @author Oliver Lohmann <oliloh@de.ibm.com> - * - * @brief The pfiflash library offers an interface for using the - * pfiflash * utility. - */ - -#include <stdio.h> /* FILE */ - -#define PFIFLASH_MAX_ERR_BUF_SIZE 1024 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum pdd_handling_t -{ - PDD_KEEP = 0, - PDD_MERGE, - PDD_OVERWRITE, - PDD_HANDLING_NUM, /* always the last item */ -} pdd_handling_t; /**< Possible PDD handle algorithms. */ - -/** - * @brief Flashes a PFI file to UBI Device 0. - * @param complete [0|1] Do a complete system update. - * @param seqnum Index in a redundant group. - * @param compare [0|1] Compare contents. - * @param pdd_handling The PDD handling algorithm. - * @param rawdev Device to use for raw flashing - * @param err_buf An error buffer. - * @param err_buf_size Size of the error buffer. - */ -int pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare, - pdd_handling_t pdd_handling, const char* rawdev, - char *err_buf, size_t err_buf_size); - -/** - * @brief Flashes a PFI file to UBI Device 0. - * @param complete [0|1] Do a complete system update. - * @param seqnum Index in a redundant group. - * @param pdd_handling The PDD handling algorithm. - * @param err_buf An error buffer. - * @param err_buf_size Size of the error buffer. - */ -int pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling, - char *err_buf, size_t err_buf_size); - -#ifdef __cplusplus -} -#endif - -#endif /* __PFIFLASH_H__ */ diff --git a/ubi-utils/sort-me-out/pfiflash_error.h b/ubi-utils/sort-me-out/pfiflash_error.h deleted file mode 100644 index 0f27f4a..0000000 --- a/ubi-utils/sort-me-out/pfiflash_error.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef __PFIFLASH_ERROR_H__ -#define __PFIFLASH_ERROR_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Author: Drake Dowsett <dowsett@de.ibm.com> - * Contact: Andreas Arnez <arnez@de.ibm.com> - */ - -enum pfiflash_err { - PFIFLASH_ERR_EOF = 1, - PFIFLASH_ERR_FIO, - PFIFLASH_ERR_UBI_OPEN, - PFIFLASH_ERR_UBI_CLOSE, - PFIFLASH_ERR_UBI_MKVOL, - PFIFLASH_ERR_UBI_RMVOL, - PFIFLASH_ERR_UBI_VOL_UPDATE, - PFIFLASH_ERR_UBI_VOL_FOPEN, - PFIFLASH_ERR_UBI_UNKNOWN, - PFIFLASH_ERR_UBI_VID_OOB, - PFIFLASH_ERR_BOOTENV_CREATE, - PFIFLASH_ERR_BOOTENV_READ, - PFIFLASH_ERR_BOOTENV_SIZE, - PFIFLASH_ERR_BOOTENV_WRITE, - PFIFLASH_ERR_PDD_UNKNOWN, - PFIFLASH_ERR_MTD_OPEN, - PFIFLASH_ERR_MTD_CLOSE, - PFIFLASH_ERR_CRC_CHECK, - PFIFLASH_ERR_MTD_ERASE, - PFIFLASH_ERR_COMPARE, - PFIFLASH_CMP_DIFF -}; - -const char *const PFIFLASH_ERRSTR[] = { - "", - "unexpected EOF", - "file I/O error", - "couldn't open UBI", - "couldn't close UBI", - "couldn't make UBI volume %d", - "couldn't remove UBI volume %d", - "couldn't update UBI volume %d", - "couldn't open UBI volume %d", - "unknown UBI operation", - "PFI data contains out of bounds UBI id %d", - "couldn't create bootenv%s", - "couldn't read bootenv", - "couldn't resize bootenv", - "couldn't write bootenv on ubi%d_%d", - "unknown PDD handling algorithm", - "couldn't open MTD device %s", - "couldn't close MTD device %s", - "CRC check failed: given=0x%08x, calculated=0x%08x", - "couldn't erase raw mtd region", - "couldn't compare volumes", - "on-flash data differ from pfi data, update is neccessary" -}; - -#endif /* __PFIFLASH_ERROR_H__ */ diff --git a/ubi-utils/sort-me-out/reader.c b/ubi-utils/sort-me-out/reader.c deleted file mode 100644 index 0ea8c6d..0000000 --- a/ubi-utils/sort-me-out/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/sort-me-out/reader.h b/ubi-utils/sort-me-out/reader.h deleted file mode 100644 index 715e464..0000000 --- a/ubi-utils/sort-me-out/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/sort-me-out/run_all.sh b/ubi-utils/sort-me-out/run_all.sh deleted file mode 100755 index 040bcbd..0000000 --- a/ubi-utils/sort-me-out/run_all.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/sh - -exit_success () -{ - echo "UBI Utils Test Scripts - SUCCESS!" - exit 0 -} - -exit_failure () -{ - echo $1 - echo "UBI Utils Test Scripts - FAILED!" - exit 1 -} - -echo UBI Utils Test Scripts - -devno=$1 -logfile=temp-test-log.txt - -if test -z "$devno"; -then - echo "Usage is $0 <mtd device number>" - exit 1 -fi - -cwd=`pwd` || exit_failure "pwd failed" - -log="${cwd}/${logfile}" - -PATH=$PATH:$cwd:.. - -cat /dev/null > $log || exit_failure "Failed to create $log" - -echo "Setting up for jffs2_test.sh" | tee -a $log - -avail=`cat /sys/class/ubi/ubi${devno}/avail_eraseblocks` -size=`cat /sys/class/ubi/ubi${devno}/eraseblock_size` - -bytes=`expr $avail \* $size` - -ubimkvol -d$devno -s$bytes -n0 -Njtstvol || exit_failure "ubimkvol failed" - -mkdir -p /mnt/test_file_system || exit_failure "mkdir failed" - -mtd=`cat /proc/mtd | grep jtstvol | cut -d: -f1` - -if test -z "$mtd"; -then - exit_failure "mtd device not found" -fi - -mount -t jffs2 $mtd /mnt/test_file_system || exit_failure "mount failed" - -cd /mnt/test_file_system || exit_failure "cd failed" - -echo Running jffs2_test.sh | tee -a $log - -jffs2_test.sh >> $log 2>&1 || exit_failure "jffs2_test.sh failed" - -rm -f * - -cd $cwd || exit_failure "cd failed" - -umount /mnt/test_file_system || exit_failure "umount failed" - -ubirmvol -d$devno -n0 || exit_failure "ubirmvol failed" - -major=`cat /sys/class/ubi/ubi${devno}/dev | cut -d: -f1` - -for minor in `seq 0 32`; do - if test ! -e /dev/ubi${devno}_$minor ; - then - mknod /dev/ubi${devno}_$minor c $major $(($minor + 1)) - fi -done - -rm -f testdata.bin readdata.bin - -echo Running ubi_jffs2_test.sh | tee -a $log - -ubi_jffs2_test.sh >> $log 2>&1 || exit_failure "ubi_jffs2_test.sh failed" - -echo Running ubi_test.sh | tee -a $log - -ubi_test.sh >> $log 2>&1 || exit_failure "ubi_test.sh failed" - -for minor in `seq 0 32`; do - if test -e /sys/class/ubi/ubi${devno}/$minor; - then - ubirmvol -d$devno -n$minor || exit_failure "ubirmvol failed" - fi -done - -echo Running ubi_tools_test.sh | tee -a $log - -ubi_tools_test.sh >> $log 2>&1 || exit_failure "ubi_tools_test failed" - -rm -f $log - -exit_success diff --git a/ubi-utils/sort-me-out/test.cfg b/ubi-utils/sort-me-out/test.cfg deleted file mode 100644 index 0b5ec48..0000000 --- a/ubi-utils/sort-me-out/test.cfg +++ /dev/null @@ -1,23 +0,0 @@ -[targets] -test_complete=spl,kernel,rootfs - -[spl] -image=test_u-boot.bin -ubi_ids=10,11 -ubi_size=1MiB -ubi_type=static -ubi_names=test_spl_0,test_spl_1 - -[kernel] -image=test_vmlinux.bin -ubi_ids=12,13 -ubi_size=2MiB -ubi_type=static -ubi_names=test_kernel_0,test_kernel_1 - -[rootfs] -image=test_rootfs.bin -ubi_ids=14,15 -ubi_size=2MiB -ubi_type=dynamic -ubi_names=test_rootfs_0,test_rootfs_1 diff --git a/ubi-utils/sort-me-out/ubi_test.sh b/ubi-utils/sort-me-out/ubi_test.sh deleted file mode 100755 index 73e4b19..0000000 --- a/ubi-utils/sort-me-out/ubi_test.sh +++ /dev/null @@ -1,328 +0,0 @@ -#!/bin/sh -# -# UBI Volume creation/deletion/write/read test script -# -# Written in shell language to reduce dependencies to more sophisticated -# interpreters, which may not be available on some stupid platforms. -# -# Author: Frank Haverkamp <haver@vnet.ibm.com> -# -# 1.0 Initial version -# 1.1 Use ubiupdatevol instead of ubiwritevol -# - -VERSION="1.1" - -export PATH=$PATH:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/ - -UBIMKVOL=ubimkvol -UBIRMVOL=ubirmvol -UBIUPDATEVOL=ubiupdatevol - -# 128 KiB 131072 -# 256 KiB 262144 -# 512 KiB 524288 - -SIZE_512K=524288 -SIZE_1M=1310720 - -SELF=$0 -MINVOL=10 -MAXVOL=12 - -# -# To have a standardized output I define the following function to be -# used when a test was ok or when it failed. -# -failed () -{ - echo "FAILED" -} - -passed () -{ - echo "PASSED" -} - -# -# Print sucess message. Consider to exit with zero as return code. -# -exit_success () -{ - echo "SUCCESS" - exit 0 -} - -# -# Print failure message. Consider to exit with non zero return code. -# -exit_failure () -{ - echo "FAILED" - exit 1 -} - -############################################################################### -# -# START -# -############################################################################### - -fix_sysfs_issue () -{ - echo -n "*** Fixing the sysfs issue with the /dev nodes ... " - - minor=0 - major=`grep ubi0 /proc/devices | sed -e 's/\(.*\) ubi0/\1/'` - - rm -rf /dev/ubi0 - mknod /dev/ubi0 c $major 0 - - for minor in `seq 0 $MAXVOL`; do - ### echo " mknod /dev/ubi0_$minor c $major $(($minor + 1))" - rm -rf /dev/ubi0_$minor - mknod /dev/ubi0_$minor c $major $(($minor + 1)) - done - passed -} - -# delete_volume - Delete a volume. If it does not exist, do not try -# to delete it. -# @id: volume id -# -delete_volume () -{ - volume=$1 - - ### FIXME broken sysfs!!!! - if [ -e /sys/class/ubi/$volume -o -e /sys/class/ubi/ubi0/$volume -o -e /sys/class/ubi/ubi0_$volume ]; then - - echo -n "*** Truncate volume if it exists ... " - $UBIUPDATEVOL -d0 -n$volume -t - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - - echo -n "*** Delete volume if it exists ... " - $UBIRMVOL -d0 -n$volume - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - fi -} - -mkvol_rmvol_test () -{ - type=$1 - -### Test if volume delete on non-existing volumes fails nicely - - for i in `seq $MINVOL $MAXVOL`; do - echo "*** Delete if exist or not $i ... " - - delete_volume $i - passed - done - -### Now deleting volumes must fail - - for i in `seq $MINVOL $MAXVOL`; do - echo "*** Trying to delete non existing UBI Volume $i ... " - - $UBIRMVOL -d0 -n$i - if [ $? -eq "0" ] ; then - exit_failure - fi - passed - done - -### Test if volume creation works ok - - for i in `seq $MINVOL $MAXVOL`; do - echo "*** Creating UBI Volume $i ... " - echo " $UBIMKVOL -d0 -n$i -t$type -NNEW$i -s $SIZE_512K" - - $UBIMKVOL -d0 -n$i -t$type -N"NEW$i" -s $SIZE_512K - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - done - -### Now deleting volumes must be ok - - for i in `seq $MINVOL $MAXVOL`; do - echo "*** Trying to delete UBI Volume $i ... " - - $UBIRMVOL -d0 -n$i - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - done - -### Now allocate too large volume - - echo -n "*** Try to create too large volume" - $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s 800000000 - if [ $? -eq "0" ] ; then - exit_failure - fi - passed -} - -# writevol_test - Tests volume creation and writing data to it. -# -# @size: Size of random data to write -# @type: Volume type static or dynamic -# -writevol_test () -{ - size=$1 - type=$2 - - echo "*** Write volume test with size $size" - -### Make sure that volume exist, delete existing volume, create new - - delete_volume $MINVOL - - echo -n "*** Try to create volume ... " - $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s $SIZE_1M - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - -### Try to create same volume again - echo -n "*** Try to create some volume again, this must fail ... " - $UBIMKVOL -d0 -n$MINVOL -t$type -N"NEW$MINVOL" -s $SIZE_1M - if [ $? -eq "0" ] ; then - exit_failure - fi - passed - -### Now create test data, write it, read it, compare it - echo -n "*** Create test data ... " - dd if=/dev/urandom of=testdata.bin bs=$size count=1 - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - - echo "*** Now writing data to volume ... " - # sleep 5 - ls -l testdata.bin - echo " $UBIUPDATEVOL -d0 -n$MINVOL testdata.bin" - $UBIUPDATEVOL -d0 -n$MINVOL testdata.bin - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - - if [ $type = "static" ] ; then - echo "*** Download data with cat ... " - cat /dev/ubi0_$MINVOL > readdata.bin - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - else - echo "*** Download data with dd bs=1 ... " - dd if=/dev/ubi0_$MINVOL of=readdata.bin bs=$size count=1 - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - - # Size 1 does not work with this test ... - # - #echo "*** Download data with dd bs=$size ... " - #dd if=/dev/ubi0_$MINVOL of=readdata2.bin bs=$size count=1 - #if [ $? -ne "0" ] ; then - # exit_failure - #fi - #passed - - #echo -n "*** Comparing data (1) ... " - #cmp readdata.bin readdata2.bin - #if [ $? -ne "0" ] ; then - # exit_failure - #fi - #passed - fi - - echo -n "*** Comparing data ... " - cmp readdata.bin testdata.bin - if [ $? -ne "0" ] ; then - exit_failure - fi - passed -} - -echo "***********************************************************************" -echo "* UBI Testing starts now ... *" -echo "* Good luck! *" -echo "***********************************************************************" - -# Set to zero if not running on example hardware -grep ubi /proc/devices > /dev/null -if [ $? -ne "0" ]; then - echo "No UBI found in /proc/devices! I am broken!" - exit_failure -fi - -# Set to zero if not running on example hardware -grep 1142 /proc/cpuinfo > /dev/null -if [ $? -eq "0" ]; then - echo "Running on example hardware" - mount -o remount,rw / / - sleep 1 - fix_sysfs_issue -else - echo "Running on Artems hardware" -fi - -echo "***********************************************************************" -echo "* mkvol/rmvol testing for static volumes ... *" -echo "***********************************************************************" - -mkvol_rmvol_test static - -echo "***********************************************************************" -echo "* mkvol/rmvol testing for dynamic volumes ... *" -echo "***********************************************************************" - -mkvol_rmvol_test dynamic - -echo "***********************************************************************" -echo "* write to static volumes ... *" -echo "***********************************************************************" - -# 10 Erase blocks = (128 KiB - 64 * 2) * 10 -# = 1309440 bytes -# 128 KiB 131072 -# 256 KiB 262144 -# 512 KiB 524288 - -for size in 262144 131073 131072 2048 1 4096 12800 31313 ; do - writevol_test $size static -done - -echo "***********************************************************************" -echo "* write to dynamic volumes ... *" -echo "***********************************************************************" -echo "VERSION: $VERSION" - -for size in 131073 131072 2048 1 4096 12800 31313 262144 ; do - writevol_test $size dynamic -done - -echo "***********************************************************************" -echo "* Congratulations, no errors found! *" -echo "* Have fun with your cool UBI system! *" -echo "***********************************************************************" - -exit_success diff --git a/ubi-utils/sort-me-out/ubi_tools_test.sh b/ubi-utils/sort-me-out/ubi_tools_test.sh deleted file mode 100755 index 7f121f1..0000000 --- a/ubi-utils/sort-me-out/ubi_tools_test.sh +++ /dev/null @@ -1,252 +0,0 @@ -#!/bin/sh -# -# UBI Volume creation/deletion/write/read test script. -# Uses our flash update tools and the associated toolchain for flash -# image creation. -# -# Written in shell language to reduce dependencies to more sophisticated -# interpreters, which may not be available on some stupid platforms. -# -# Author: Frank Haverkamp <haver@vnet.ibm.com> -# -# 1.0 Initial version -# - -VERSION="1.0" - -export PATH=$PATH:~/bin:/usr/local/bin:/home/dedekind/work/prj/ubi/tools/flashutils/bin/ - -UBIMKVOL=ubimkvol -UBIRMVOL=ubirmvol -UBIWRITEVOL=ubiupdatevol -PFIFLASH=pfiflash -CMP=cmp - -MAXVOL=32 - -test_pfi=test_complete.pfi -real_pfi=example_complete.pfi - -# 128 KiB 131072 -# 256 KiB 262144 -# 512 KiB 524288 - -# -# To have a standardized output I define the following function to be -# used when a test was ok or when it failed. -# -failed () -{ - echo "FAILED" -} - -passed () -{ - echo "PASSED" -} - -# -# Print sucess message. Consider to exit with zero as return code. -# -exit_success () -{ - echo "SUCCESS" - exit 0 -} - -# -# Print failure message. Consider to exit with non zero return code. -# -exit_failure () -{ - echo "FAILED" - exit 1 -} - -############################################################################### -# -# START -# -############################################################################### - -fix_sysfs_issue () -{ - echo -n "*** Fixing the sysfs issue with the /dev nodes ... " - - minor=0 - major=`grep ubi0 /proc/devices | sed -e 's/\(.*\) ubi0/\1/'` - - rm -rf /dev/ubi0 - mknod /dev/ubi0 c $major 0 - - for minor in `seq 0 $MAXVOL`; do - ### echo " mknod /dev/ubi0_$minor c $major $(($minor + 1))" - rm -rf /dev/ubi0_$minor - mknod /dev/ubi0_$minor c $major $(($minor + 1)) - done - passed -} - -# delete_volume - Delete a volume. If it does not exist, do not try -# to delete it. -# @id: volume id -# -delete_volume () -{ - volume=$1 - - ### FIXME broken sysfs!!!! - if [ -e /sys/class/ubi/$volume -o -e /sys/class/ubi/ubi0/$volume -o -e /sys/class/ubi/ubi0_$volume ]; then - - echo -n "*** Truncate volume if it exists ... " - $UBIWRITEVOL -d0 -n$volume -t - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - - echo -n "*** Delete volume if it exists ... " - $UBIRMVOL -d0 -n$volume - if [ $? -ne "0" ] ; then - exit_failure - fi - passed - fi -} - -echo "***********************************************************************" -echo "* UBI Tools Testing starts now ... *" -echo "* Good luck! *" -echo "***********************************************************************" - -# Set to zero if not running on example hardware -grep ubi /proc/devices > /dev/null -if [ $? -ne "0" ]; then - echo "No UBI found in /proc/devices! I am broken!" - exit_failure -fi - -# Set to zero if not running on example hardware -grep 1142 /proc/cpuinfo > /dev/null -if [ $? -eq "0" ]; then - echo "Running on example hardware" - mount -o remount,rw / / - sleep 1 - fix_sysfs_issue -else - echo "Running on other hardware" -fi - -### Test basic stuff -pfiflash_basic () -{ - echo "Calling pfiflash with test-data ... " - echo " $PFIFLASH $test_pfi" - $PFIFLASH $test_pfi - if [ $? -ne "0" ]; then - echo "Uhhh something went wrong!" - exit_failure - fi - passed - - echo "Testing if data is correct 10 and 11 ... " - $CMP /dev/ubi0_10 /dev/ubi0_11 - if [ $? -ne "0" ]; then - echo "Mirrored volumes not equal!" - exit_failure - fi - passed - - echo "Comparing against original data ... " - $CMP /dev/ubi0_10 test_u-boot.bin - if [ $? -ne "0" ]; then - echo "Compared volume not equal!" - exit_failure - fi - passed - - echo "Testing if data is correct 12 and 13 ... " - $CMP /dev/ubi0_12 /dev/ubi0_13 - if [ $? -ne "0" ]; then - echo "Mirrored volumes not equal!" - exit_failure - fi - passed - - echo "Comparing against original data ... " - $CMP /dev/ubi0_12 test_vmlinux.bin - if [ $? -ne "0" ]; then - echo "Compared volume not equal!" - exit_failure - fi - passed - - echo "Testing if data is correct 14 and 15 ... " - $CMP /dev/ubi0_14 /dev/ubi0_15 - if [ $? -ne "0" ]; then - echo "Mirrored volumes not equal!" - exit_failure - fi - passed -} - -### Test each and everything -pfiflash_advanced () -{ - if [ -e example_complete.pfi ]; then - echo "Calling pfiflash with real data ... " - $PFIFLASH -p overwrite --complete example_complete.pfi - if [ $? -ne "0" ]; then - echo "Uhhh something went wrong!" - exit_failure - fi - passed - - echo "Testing if data is correct 2 and 3 ... " - $CMP /dev/ubi0_2 /dev/ubi0_3 - if [ $? -ne "0" ]; then - echo "Mirrored volumes not equal!" - exit_failure - fi - passed - - echo "Comparing against original data ... " - $CMP /dev/ubi0_2 u-boot.bin - if [ $? -ne "0" ]; then - echo "Compared volume not equal!" - exit_failure - fi - passed - - echo "Testing if data is correct 6 and 7 ... " - $CMP /dev/ubi0_6 /dev/ubi0_7 - if [ $? -ne "0" ]; then - echo "Mirrored volumes not equal!" - exit_failure - fi - passed - - echo "Comparing against original data ... " - $CMP /dev/ubi0_6 vmlinux.bin - if [ $? -ne "0" ]; then - echo "Compared volume not equal!" - exit_failure - fi - passed - fi -} - -echo "***********************************************************************" -echo "* Testing pfiflash ... *" -echo "***********************************************************************" -echo "VERSION: $VERSION" - -pfiflash_basic -pfiflash_advanced - -echo "***********************************************************************" -echo "* Congratulations, no errors found! *" -echo "* Have fun with your cool UBI system! *" -echo "***********************************************************************" - -exit_success diff --git a/ubi-utils/sort-me-out/ubicrc32.pl b/ubi-utils/sort-me-out/ubicrc32.pl deleted file mode 100644 index 92711cb..0000000 --- a/ubi-utils/sort-me-out/ubicrc32.pl +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/perl -w - -# Subroutine crc32(): Calculates the CRC on a given string. - -{ - my @table = (); - - # @brief Calculate CRC32 for a given string. - sub crc32 - { - unless (@table) { - # Initialize the CRC table - my $poly = 0xEDB88320; - @table = (); - - for my $i (0..255) { - my $c = $i; - - for my $j (0..7) { - $c = ($c & 1) ? (($c >> 1) ^ $poly) : ($c >> 1); - } - $table[$i] = $c; - } - } - my $s = shift; # string to calculate the CRC for - my $crc = shift; # CRC start value - - defined($crc) - or $crc = 0xffffffff; # Default CRC start value - - for (my $i = 0; $i < length($s); $i++) { - $crc = $table[($crc ^ ord(substr($s, $i, 1))) & 0xff] - ^ ($crc >> 8); - } - return $crc; - } -} - -sub crc32_on_file -{ - my $file = shift; - - my $crc32 = crc32(''); - my $buf = ''; - my $ret = 0; - - while ($ret = read($file, $buf, 8192)) { - $crc32 = crc32($buf, $crc32); - } - defined($ret) - or return undef; - printf("0x%x\n", $crc32); -} - - -# Main routine: Calculate the CRCs on the given files and print the -# results. - -{ - if (@ARGV) { - while (my $path = shift) { - my $file; - open $file, "<", $path - or die "Error opening '$path'.\n"; - - &crc32_on_file($file) - or die "Error reading from '$path'.\n"; - close $file; - } - } else { - &crc32_on_file(\*STDIN) - or die "Error reading from stdin.\n"; - } -} diff --git a/ubi-utils/sort-me-out/ubigen.c b/ubi-utils/sort-me-out/ubigen.c deleted file mode 100644 index 35fad27..0000000 --- a/ubi-utils/sort-me-out/ubigen.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * An utility to generate UBI images. - * - * Authors: Oliver Lohmann - * Artem Bityutskiy - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <getopt.h> -#include <unistd.h> -#include <sys/stat.h> -#include <mtd/ubi-header.h> - -#include "ubigen.h" -#include "common.h" - -#define PROGRAM_VERSION "1.4" -#define PROGRAM_NAME "ubigen" - -struct args { - FILE *fp_in; - FILE *fp_out; - int peb_size; - int id; - int min_io_size; - int type; - int sub_page_size; - int alignment; - int vid_hdr_offs; - int ec; - int ubi_ver; -}; - -struct args args = { - .fp_in = NULL, - .fp_out = NULL, - .peb_size = -1, - .id = -1, - .min_io_size = -1, - .type = UBI_VID_DYNAMIC, - .sub_page_size = -1, - .alignment = 1, - .vid_hdr_offs = 0, - .ec = 0, - .ubi_ver = 0, -}; - -static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -" - a tool for adding UBI headers to a binary image.\n" -"Note, the images generated by this program are not ready to be used\n" -"because they do not contain the volume table. If not sure about one\n" -"of the parameters, do not specify and let the utility to use default\n" -"values."; - -static const char *optionsstr = -"-i, --infile=<filename> the input file\n" -"-o, --outfile=<filename> the output file (default is stdout)\n" -"-b, --peb-size=<bytes> size of the physical eraseblock of the flash this\n" -" UBI image is created for in bytes, kilobytes (KiB),\n" -" or megabytes (MiB) (mandatory parameter)\n" -"-I, --vol-id=<num> volume ID (mandatory parameter)\n" -"-m, --min-io-size=<bytes> minimum input/output unit size of the flash in bytes\n" -" kilobytes (KiB), or megabytes (MiB) (mandatory\n" -" parameter); e.g. this is NAND page size in case of\n" -" NAND flash\n" -"-t, --type=<static|dynamic> volume type: dynamic or static (default is dynamic)\n" -"-s, --sub-page-size=<bytes> minimum input/output unit used for UBI headers, e.g.\n" -" sub-page size in case of NAND flash (equivalent to\n" -" the minimum input/output unit size by default)\n" -"-a, --alignment=<bytes> volume alignment in bytes, kilobytes (KiB), or\n" -" megabytes (MiB) (default is 1)\n" -"-O, --vid-hdr-offset=<num> offset if the VID header from start of the physical\n" -" eraseblock (default is the second minimum I/O unit\n" -" or sub-page, if it was specified)\n" -"-e, --erase-counter=<num> the erase counter value to put to EC headers\n" -" (default is 0)\n" -"-x, --ubi-ver=<num> UBI version number to put to EC headers\n" -" (default is 1)\n" -"-h, --help print help message\n" -"-V, --version print program version"; - -static const char *usage = -"Usage: " PROGRAM_NAME " -i <input file> -o <output file> -b <PEB size>\n" -" -I <volume ID> -m <min I/O unit size> [-s <sub-page size>]\n" -" [-a <alignment>] [-O <volume ID header offset>]\n" -" [-e <erase counter value>] [-x <UBI version>] [-h] [-V]"; - -struct option long_options[] = { - { .name = "infile", .has_arg = 1, .flag = NULL, .val = 'i' }, - { .name = "outfile", .has_arg = 1, .flag = NULL, .val = 'o' }, - { .name = "peb-size", .has_arg = 1, .flag = NULL, .val = 'b' }, - { .name = "vol-id", .has_arg = 1, .flag = NULL, .val = 'I' }, - { .name = "min-io-size", .has_arg = 1, .flag = NULL, .val = 'm' }, - { .name = "type", .has_arg = 1, .flag = NULL, .val = 't' }, - { .name = "sub-page-size", .has_arg = 1, .flag = NULL, .val = 's' }, - { .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'a' }, - { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' }, - { .name = "erase-counter", .has_arg = 1, .flag = NULL, .val = 'e' }, - { .name = "ubi-ver", .has_arg = 1, .flag = NULL, .val = 'x' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0} -}; - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key; - char *endp; - - key = getopt_long(argc, argv, "i:o:b:I:m:t:s:a:O:e:x:hV", - long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'o': - args.fp_out = fopen(optarg, "wb"); - if (!args.fp_out) { - errmsg("cannot open file \"%s\"", optarg); - return -1; - } - break; - - case 'i': - args.fp_in = fopen(optarg, "rb"); - if (!args.fp_in) { - errmsg("cannot open file \"%s\"", optarg); - return -1; - } - break; - - case 'b': - args.peb_size = strtoull(optarg, &endp, 0); - if (endp == optarg || args.peb_size <= 0) { - errmsg("bad physical eraseblock size: \"%s\"", optarg); - return -1; - } - if (*endp != '\0') { - int mult = ubiutils_get_multiplier(endp); - - if (mult == -1) { - errmsg("bad size specifier: \"%s\" - " - "should be 'KiB', 'MiB' or 'GiB'", endp); - return -1; - } - args.peb_size *= mult; - } - break; - - case 'm': - args.min_io_size = strtoull(optarg, &endp, 0); - if (endp == optarg || args.min_io_size <= 0) { - errmsg("bad min. I/O unit size: \"%s\"", optarg); - return -1; - } - if (*endp != '\0') { - int mult = ubiutils_get_multiplier(endp); - - if (mult == -1) { - errmsg("bad size specifier: \"%s\" - " - "should be 'KiB', 'MiB' or 'GiB'", endp); - return -1; - } - args.min_io_size *= mult; - } - break; - - case 'e': - args.ec = strtoul(optarg, &endp, 0); - if (endp == optarg || args.ec < 0) { - errmsg("bad erase counter value: \"%s\"", optarg); - return -1; - } - break; - - case 'I': - args.id = strtoul(optarg, &endp, 0); - if (endp == optarg || args.id < 0) { - errmsg("bad volume ID: \"%s\"", optarg); - return -1; - } - break; - - case 't': - if (!strcmp(optarg, "dynamic")) - args.type = UBI_VID_DYNAMIC; - else if (!strcmp(optarg, "static")) - args.type = UBI_VID_STATIC; - else { - errmsg("bad volume type: \"%s\"", optarg); - return -1; - } - break; - - case 'x': - args.ubi_ver = strtoul(optarg, &endp, 0); - if (endp == optarg || args.ubi_ver < 0) { - errmsg("bad UBI version: \"%s\"", optarg); - return -1; - } - break; - - case 'O': - args.vid_hdr_offs = strtoul(optarg, &endp, 0); - if (endp == optarg || args.vid_hdr_offs < 0) { - errmsg("bad VID header offset: \"%s\"", optarg); - return -1; - } - break; - - case 'h': - fprintf(stderr, "%s\n\n", doc); - fprintf(stderr, "%s\n\n", usage); - fprintf(stderr, "%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - case ':': - errmsg("parameter is missing"); - return -1; - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (!args.fp_in) { - errmsg("input file was not specified (use -h for help)"); - return -1; - } - - if (!args.fp_out) - args.fp_out = stdout; - - if (args.id < 0) { - errmsg("wolume ID was not specified (use -h for help)"); - return -1; - } - - if (args.peb_size < 0) { - errmsg("physical eraseblock size was not specified " - "(use -h for help)"); - return -1; - } - - if (args.min_io_size < 0) { - errmsg("min. I/O unit size was not specified " - "(use -h for help)"); - return -1; - } - - if (args.sub_page_size < 0) - args.sub_page_size = args.min_io_size; - - return 0; -} - - -int main(int argc, char * const argv[]) -{ - int err; - ubi_info_t u; - struct stat file_info; - off_t input_len = 0; /* only used in static volumes */ - - ubigen_init(); - - err = parse_opt(argc, argv); - if (err) - return -1; - - if (fstat(fileno(args.fp_in), &file_info) != 0) { - fprintf(stderr, "Cannot fetch file size " - "from input file.\n"); - } - input_len = file_info.st_size; - - err = ubigen_create(&u, (uint32_t)args.id, args.type, - args.peb_size, args.ec, args.alignment, - args.ubi_ver, args.vid_hdr_offs, 0 ,input_len, - args.fp_in, args.fp_out); - - if (err) { - fprintf(stderr, "Cannot create UBI info handler err: %d\n", err); - return -1; - } - - err = ubigen_write_complete(u); - if (err != 0) { - fprintf(stderr, "Error converting input data.\n"); - return -1; - } - - err = ubigen_destroy(&u); - return err; -} diff --git a/ubi-utils/sort-me-out/ubimirror.c b/ubi-utils/sort-me-out/ubimirror.c deleted file mode 100644 index 2cc4596..0000000 --- a/ubi-utils/sort-me-out/ubimirror.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - * - * 1.2 Removed argp because we want to use uClibc. - * 1.3 Minor cleanups - * 1.4 Migrated to new libubi - */ - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> -#include <unistd.h> -#include <errno.h> -#include <mtd/ubi-header.h> - -#include "config.h" -#include "error.h" -#include "example_ubi.h" -#include "ubimirror.h" - -#define PROGRAM_VERSION "1.4" - -typedef enum action_t { - ACT_NORMAL = 0, - ACT_ARGP_ABORT, - ACT_ARGP_ERR, -} action_t; - -#define ABORT_ARGP do { \ - args->action = ACT_ARGP_ABORT; \ -} while (0) - -#define ERR_ARGP do { \ - args->action = ACT_ARGP_ERR; \ -} while (0) - -#define VOL_ARGS_MAX 2 - -static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" - "ubimirror - mirrors ubi volumes.\n"; - -static const char *optionsstr = -" -c, --copyright Print copyright information.\n" -" -s, --side=<seqnum> Use the side <seqnum> as source.\n" -" -?, --help Give this help list\n" -" --usage Give a short usage message\n" -" -V, --version Print program version\n"; - -static const char *usage = -"Usage: ubimirror [-c?V] [-s <seqnum>] [--copyright] [--side=<seqnum>]\n" -" [--help] [--usage] [--version] <source> <destination>\n"; - -static const char copyright [] __attribute__((unused)) = - "(C) IBM Coorporation 2007"; - -struct option long_options[] = { - { .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' }, - { .name = "side", .has_arg = 1, .flag = NULL, .val = 's' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, - { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0} -}; - -typedef struct myargs { - action_t action; - int side; - int vol_no; /* index of current volume */ - /* @FIXME replace by bootenv_list, makes live easier */ - /* @FIXME remove the constraint of two entries in the array */ - const char* vol[VOL_ARGS_MAX]; /* comma separated list of src/dst - volumes */ - char *arg1; - char **options; /* [STRING...] */ -} myargs; - -static int -get_update_side(const char* str) -{ - uint32_t i = strtoul(str, NULL, 0); - - if ((i != 0) && (i != 1)) { - return -1; - } - return i; -} - - -static int -parse_opt(int argc, char **argv, myargs *args) -{ - while (1) { - int key; - - key = getopt_long(argc, argv, "cs:?V", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'c': - err_msg("%s", copyright); - ABORT_ARGP; - break; - case 's': - args->side = get_update_side(optarg); - if (args->side < 0) { - err_msg("Unsupported seqnum: %s.\n" - "Supported seqnums are '0' " - "and '1'\n", optarg); - ERR_ARGP; - } - break; - case '?': /* help */ - err_msg("Usage: ubimirror [OPTION...] " - "<source> <destination>\n"); - err_msg("%s", doc); - err_msg("%s", optionsstr); - err_msg("\nReport bugs to %s\n", - PACKAGE_BUGREPORT); - exit(0); - break; - case 'V': - err_msg("%s", PROGRAM_VERSION); - exit(0); - break; - default: - err_msg("%s", usage); - exit(-1); - } - } - - while (optind < argc) { - /* only two entries allowed */ - if (args->vol_no >= VOL_ARGS_MAX) { - err_msg("%s", usage); - ERR_ARGP; - } - args->vol[(args->vol_no)++] = argv[optind++]; - } - - return 0; -} - - -int -main(int argc, char **argv) { - int rc = 0; - unsigned int ids[VOL_ARGS_MAX]; - char err_buf[1024]; - - myargs args = { - .action = ACT_NORMAL, - .side = -1, - .vol_no = 0, - .vol = {"", ""}, - .options = NULL, - }; - - parse_opt(argc, argv, &args); - if (args.action == ACT_ARGP_ERR) { - rc = 127; - goto err; - } - if (args.action == ACT_ARGP_ABORT) { - rc = 126; - goto out; - } - if (args.vol_no < VOL_ARGS_MAX) { - fprintf(stderr, "missing volume number for %s\n", - args.vol_no == 0 ? "source and target" : "target"); - rc = 125; - goto out; - } - for( rc = 0; rc < args.vol_no; ++rc){ - char *endp; - ids[rc] = strtoul(args.vol[rc], &endp, 0); - if( *endp != '\0' ){ - fprintf(stderr, "invalid volume number %s\n", - args.vol[rc]); - rc = 125; - goto out; - } - } - rc = ubimirror(EXAMPLE_UBI_DEVICE, args.side, ids, args.vol_no, - err_buf, sizeof(err_buf)); - if( rc ){ - err_buf[sizeof err_buf - 1] = '\0'; - fprintf(stderr, err_buf); - if( rc < 0 ) - rc = -rc; - } - out: - err: - return rc; -} diff --git a/ubi-utils/sort-me-out/ubimirror.h b/ubi-utils/sort-me-out/ubimirror.h deleted file mode 100644 index d7ae2ad..0000000 --- a/ubi-utils/sort-me-out/ubimirror.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __UBIMIRROR_H__ -#define __UBIMIRROR_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - * - * An utility to mirror UBI volumes. - */ - -#include <stdint.h> - -/** - * @def EUBIMIRROR_SRC_EQ_DST - * @brief Given source volume is also in the set of destination volumes. - */ -#define EUBIMIRROR_SRC_EQ_DST 20 - -/** - * @def EUBIMIRROR_NO_SRC - * @brief The given source volume does not exist. - */ -#define EUBIMIRROR_NO_SRC 21 - -/** - * @def EUBIMIRROR_NO_DST - * @brief One of the given destination volumes does not exist. - */ -#define EUBIMIRROR_NO_DST 22 - -/** - * @brief Mirrors UBI devices from a source device (specified by seqnum) - * to n target devices. - * @param devno Device number used by the UBI operations. - * @param seqnum An index into ids (defines the src_id). - * @param ids An array of ids. - * @param ids_size The number of entries in the ids array. - * @param err_buf A buffer to store verbose error messages. - * @param err_buf_size The size of the error buffer. - * - * @note A seqnum of value < 0 defaults to a seqnum of 0. - * @note A seqnum exceeding the range of ids_size defaults to 0. - * @note An empty ids list results in a empty stmt. - * @pre The UBI volume which shall be used as source volume exists. - * @pre The UBI volumes which are defined as destination volumes exist. - * @post The content of the UBI volume which was defined as source volume - * equals the content of the volumes which were defined as destination. - */ -int ubimirror(uint32_t devno, int seqnum, uint32_t* ids, ssize_t ids_size, - char *err_buf, size_t err_buf_size); - -#endif /* __UBIMIRROR_H__ */ diff --git a/ubi-utils/sort-me-out/unubi_test.sh b/ubi-utils/sort-me-out/unubi_test.sh deleted file mode 100644 index 40dc2e2..0000000 --- a/ubi-utils/sort-me-out/unubi_test.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/sh -# -# Use raw NAND data, extract UBI image and apply tool to it. -# Test basic functionality. -# -# 2007 Frank Haverkamp <haver@vnet.ibm.com> -# - -version=1.1 - -image=data.mif -oob=oob.bin -data=data.bin -pagesize=2048 -volmax=31 -datadir=unubi_data - -# general arguments e.g. debug enablement -# unubi_args="-D" - -echo "------------------------------------------------------------------------" -echo "Testcase: ${0} Version: ${version}" -echo "------------------------------------------------------------------------" -echo "Testing nand2bin ..." -echo " Input: ${image}" -echo " Data: ${data}" -echo " OOB: ${oob}" -echo " Pagesize: ${pagesize}" -nand2bin --pagesize ${pagesize} -o ${data} -O ${oob} ${image} -echo - -echo "------------------------------------------------------------------------" -echo "Testing unubi ..." -echo "------------------------------------------------------------------------" -unubi --version -echo - -echo "------------------------------------------------------------------------" -echo "Trying to extract first ${volmax} volumes ..." -echo "------------------------------------------------------------------------" -mkdir -p ${datadir}/volumes -for v in `seq 0 ${volmax}` ; do - unubi ${unubi_args} -r${v} -d${datadir}/volumes ${data} - echo -n "." -done -echo "ok" -ls -l ${datadir}/volumes -echo - -echo "------------------------------------------------------------------------" -echo "Extracting graphics ..." -echo "------------------------------------------------------------------------" -unubi -a -d${datadir} ${data} -echo "Use gnuplot to display:" -ls ${datadir}/*.plot -ls ${datadir}/*.data -echo - -echo "------------------------------------------------------------------------" -echo "eb-split" -echo "------------------------------------------------------------------------" -unubi -e -d${datadir}/eb-split ${data} -ls -l ${datadir}/eb-split -echo - -echo "------------------------------------------------------------------------" -echo "vol-split" -echo "------------------------------------------------------------------------" -unubi -v -d${datadir}/vol-split ${data} -ls -l ${datadir}/vol-split -echo -echo "The generated images contain only the data (126KiB in our " -echo "case) not including the UBI erase count and volume info " -echo "header. For dynamic volumes the data should be the full " -echo "126KiB. Unubi cannot know how much of the data is valid. " -echo - -echo "------------------------------------------------------------------------" -echo "!vol-split" -echo "------------------------------------------------------------------------" -unubi -V -d${datadir}/vol-split! ${data} -ls -l ${datadir}/vol-split\! -echo -echo "The generated images contain the full block data of 128KiB " -echo "including the UBI erase count and volume information header." -echo - -echo "------------------------------------------------------------------------" -echo "Extracting volume info table ..." -echo "------------------------------------------------------------------------" -unubi -i -d${datadir} ${data} -echo "I strongly hope that empty ubi blocks are filled with 0xff! " -echo - -echo "------------------------------------------------------------------------" -echo "Table 0" -echo "------------------------------------------------------------------------" -cat ${datadir}/vol_info_table0 -echo - -echo "------------------------------------------------------------------------" -echo "Table 1" -echo "------------------------------------------------------------------------" -cat ${datadir}/vol_info_table1 -echo diff --git a/ubi-utils/src/bootenv.c b/ubi-utils/src/bootenv.c deleted file mode 100644 index 5a4205f..0000000 --- a/ubi-utils/src/bootenv.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> -#include <netinet/in.h> -#include <sys/stat.h> -#include <bootenv.h> - -#include "hashmap.h" -#include "error.h" - -#include <mtd/ubi-header.h> -#include "crc32.h" - -#define ubi_unused __attribute__((unused)) - -#define BOOTENV_MAXLINE 512 /* max line size of a bootenv.txt file */ - -/* Structures */ -struct bootenv { - hashmap_t map; ///< Pointer to hashmap which holds data structure. -}; - -struct bootenv_list { - hashmap_t head; ///< Pointer to list which holds the data structure. -}; - -/** - * @brief Remove the '\n' from a given line. - * @param line Input/Output line. - * @param size Size of the line. - * @param fp File Pointer. - * @return 0 - * @return or error - */ -static int -remove_lf(char *line, size_t size, FILE* fp) -{ - size_t i; - - for (i = 0; i < size; i++) { - if (line[i] == '\n') { - line[i] = '\0'; - return 0; - } - } - - if (!feof(fp)) { - return BOOTENV_EINVAL; - } - - return 0; -} - -/** - * @brief Determine if a line contains only WS. - * @param line The line to process. - * @param size Size of input line. - * @return 1 Yes, only WS. - * @return 0 No, contains data. - */ -static int -is_ws(const char *line, size_t size) -{ - size_t i = 0; - - while (i < size) { - switch (line[i]) { - case '\n': - return 1; - case '#': - return 1; - case ' ': - i++; - continue; - case '\t': - i++; - continue; - default: /* any other char -> no cmnt */ - return 0; - } - } - - return 0; -} - - -/* ------------------------------------------------------------------------- */ - -/** - * @brief Build a list from a comma seperated value string. - * @param list Pointer to hashmap structure which shall store - * the list. - * @param value Comma seperated value string. - * @return 0 - * @return or error. - */ -static int -build_list_definition(hashmap_t list, const char *value) -{ - int rc = 0; - char *str = NULL; - char *ptr = NULL; - size_t len, i, j; - - /* str: val1,val2 , val4,...,valN */ - len = strlen(value); - str = (char*) malloc((len+1) * sizeof(char)); - - /* 1. reformat string: remove spaces */ - for (i = 0, j = 0; i < len; i++) { - if (value[i] == ' ') - continue; - - str[j] = value[i]; - j++; - } - str[j] = '\0'; - - /* str: val1,val2,val4,...,valN\0*/ - /* 2. replace ',' seperator with '\0' */ - len = strlen(str); - for (i = 0; i < len; i++) { - if (str[i] == ',') { - str[i] = '\0'; - } - } - - /* str: val1\0val2\0val4\0...\0valN\0*/ - /* 3. insert definitions into a hash map, using it like a list */ - i = j = 0; - ptr = str; - while (((i = strlen(ptr)) > 0) && (j < len)) { - rc = hashmap_add(list, ptr, ""); - if (rc != 0) { - free(str); - return rc; - } - j += i+1; - if (j < len) - ptr += i+1; - } - - free(str); - return rc; -} - -/** - * @brief Extract a key value pair and add it to a hashmap - * @param str Input string which contains a key value pair. - * @param env The updated handle which contains the new pair. - * @return 0 - * @return or error - * @note The input string format is: "key=value" - */ -static int -extract_pair(const char *str, bootenv_t env) -{ - int rc = 0; - char *key = NULL; - char *val = NULL; - - key = strdup(str); - if (key == NULL) - return -ENOMEM; - - val = strstr(key, "="); - if (val == NULL) { - rc = BOOTENV_EBADENTRY; - goto err; - } - - *val = '\0'; /* split strings */ - val++; - - rc = bootenv_set(env, key, val); - - err: - free(key); - return rc; -} - -int -bootenv_destroy(bootenv_t* env) -{ - int rc = 0; - - if (env == NULL || *env == NULL) - return -EINVAL; - - bootenv_t tmp = *env; - - rc = hashmap_free(tmp->map); - if (rc != 0) - return rc; - - free(tmp); - return rc; -} - -int -bootenv_create(bootenv_t* env) -{ - bootenv_t res; - res = (bootenv_t) calloc(1, sizeof(struct bootenv)); - - if (res == NULL) - return -ENOMEM; - - res->map = hashmap_new(); - - if (res->map == NULL) { - free(res); - return -ENOMEM; - } - - *env = res; - - return 0; -} - - -/** - * @brief Read a formatted buffer and scan it for valid bootenv - * key/value pairs. Add those pairs into a hashmap. - * @param env Hashmap which shall be used to hold the data. - * @param buf Formatted buffer. - * @param size Size of the buffer. - * @return 0 - * @return or error - */ -static int -rd_buffer(bootenv_t env, const char *buf, size_t size) -{ - const char *curr = buf; /* ptr to current key/value pair */ - uint32_t i, j; /* current length, chars processed */ - - if (buf[size - 1] != '\0') /* must end in '\0' */ - return BOOTENV_EFMT; - - for (j = 0; j < size; j += i, curr += i) { - /* strlen returns the size of the string upto - but not including the null terminator; - adding 1 to account for '\0' */ - i = strlen(curr) + 1; - - if (i == 1) - return 0; /* no string found */ - - if (extract_pair(curr, env) != 0) - return BOOTENV_EINVAL; - } - - return 0; -} - - -int -bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t* ret_crc) -{ - int rc; - char *buf = NULL; - size_t i = 0; - - if ((fp == NULL) || (env == NULL)) - return -EINVAL; - - /* allocate temp buffer */ - buf = (char*) calloc(1, size * sizeof(char)); - if (buf == NULL) - return -ENOMEM; - - /* FIXME Andreas, please review this I removed size-1 and - * replaced it by just size, I saw the kernel image starting - * with a 0x0060.... and not with the 0x60.... what it should - * be. Is this a tools problem or is it a problem here where - * fp is moved not to the right place due to the former size-1 - * here. - */ - while((i < size) && (!feof(fp))) { - int c = fgetc(fp); - if (c == EOF) { - /* FIXME isn't this dangerous, to update - the boot envs with incomplete data? */ - buf[i++] = '\0'; - break; /* we have enough */ - } - if (ferror(fp)) { - rc = -EIO; - goto err; - } - - buf[i++] = (char)c; - } - - /* calculate crc to return */ - if (ret_crc != NULL) { - *ret_crc = crc32(UBI_CRC32_INIT, buf, size); - } - - /* transfer to hashmap */ - rc = rd_buffer(env, buf, size); - -err: - free(buf); - return rc; -} - - -/** - * If we have a single file containing the boot-parameter size should - * be specified either as the size of the file or as BOOTENV_MAXSIZE. - * If the bootparameter are in the middle of a file we need the exact - * length of the data. - */ -int -bootenv_read(FILE* fp, bootenv_t env, size_t size) -{ - return bootenv_read_crc(fp, env, size, NULL); -} - - -int -bootenv_read_txt(FILE* fp, bootenv_t env) -{ - int rc = 0; - char *buf = NULL; - char *line = NULL; - char *lstart = NULL; - char *curr = NULL; - size_t len; - size_t size; - - if ((fp == NULL) || (env == NULL)) - return -EINVAL; - - size = BOOTENV_MAXSIZE; - - /* allocate temp buffers */ - buf = (char*) calloc(1, size * sizeof(char)); - lstart = line = (char*) calloc(1, size * sizeof(char)); - if ((buf == NULL) || (line == NULL)) { - rc = -ENOMEM; - goto err; - } - - curr = buf; - while ((line = fgets(line, size, fp)) != NULL) { - if (is_ws(line, size)) { - continue; - } - rc = remove_lf(line, BOOTENV_MAXSIZE, fp); - if (rc != 0) { - goto err; - } - - /* copy new line to binary buffer */ - len = strlen(line); - if (len > size) { - rc = -EFBIG; - goto err; - } - size -= len; /* track remaining space */ - - memcpy(curr, line, len); - curr += len + 1; /* for \0 seperator */ - } - - rc = rd_buffer(env, buf, BOOTENV_MAXSIZE); -err: - if (buf != NULL) - free(buf); - if (lstart != NULL) - free(lstart); - return rc; -} - -static int -fill_output_buffer(bootenv_t env, char *buf, size_t buf_size_max ubi_unused, - size_t *written) -{ - int rc = 0; - size_t keys_size, i; - size_t wr = 0; - const char **keys = NULL; - const char *val = NULL; - - rc = bootenv_get_key_vector(env, &keys_size, 1, &keys); - if (rc != 0) - goto err; - - for (i = 0; i < keys_size; i++) { - if (wr > BOOTENV_MAXSIZE) { - rc = -ENOSPC; - goto err; - } - - rc = bootenv_get(env, keys[i], &val); - if (rc != 0) - goto err; - - wr += snprintf(buf + wr, BOOTENV_MAXSIZE - wr, - "%s=%s", keys[i], val); - wr++; /* for \0 */ - } - - *written = wr; - -err: - if (keys != NULL) - free(keys); - - return rc; -} - -int -bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc) -{ - int rc = 0; - size_t size = 0; - char *buf = NULL; - - if ((fp == NULL) || (env == NULL)) - return -EINVAL; - - buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char)); - if (buf == NULL) - return -ENOMEM; - - - rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, &size); - if (rc != 0) - goto err; - - /* calculate crc to return */ - if (ret_crc != NULL) { - *ret_crc = crc32(UBI_CRC32_INIT, buf, size); - } - - if (fwrite(buf, size, 1, fp) != 1) { - rc = -EIO; - goto err; - } - -err: - if (buf != NULL) - free(buf); - return rc; -} - -int -bootenv_write(FILE* fp, bootenv_t env) -{ - return bootenv_write_crc(fp, env, NULL); -} - -int -bootenv_compare(bootenv_t first, bootenv_t second) -{ - int rc; - size_t written_first, written_second; - char *buf_first, *buf_second; - - if (first == NULL || second == NULL) - return -EINVAL; - - buf_first = malloc(BOOTENV_MAXSIZE); - if (!buf_first) - return -ENOMEM; - buf_second = malloc(BOOTENV_MAXSIZE); - if (!buf_second) { - rc = -ENOMEM; - goto err; - } - - rc = fill_output_buffer(first, buf_first, BOOTENV_MAXSIZE, - &written_first); - if (rc < 0) - goto err; - rc = fill_output_buffer(second, buf_second, BOOTENV_MAXSIZE, - &written_second); - if (rc < 0) - goto err; - - if (written_first != written_second) { - rc = 1; - goto err; - } - - rc = memcmp(buf_first, buf_second, written_first); - if (rc != 0) { - rc = 2; - goto err; - } - -err: - if (buf_first) - free(buf_first); - if (buf_second) - free(buf_second); - - return rc; -} - -int -bootenv_size(bootenv_t env, size_t *size) -{ - int rc = 0; - char *buf = NULL; - - if (env == NULL) - return -EINVAL; - - buf = (char*) calloc(1, BOOTENV_MAXSIZE * sizeof(char)); - if (buf == NULL) - return -ENOMEM; - - rc = fill_output_buffer(env, buf, BOOTENV_MAXSIZE, size); - if (rc != 0) - goto err; - -err: - if (buf != NULL) - free(buf); - return rc; -} - -int -bootenv_write_txt(FILE* fp, bootenv_t env) -{ - int rc = 0; - size_t size, wr, i; - const char **keys = NULL; - const char *key = NULL; - const char *val = NULL; - - if ((fp == NULL) || (env == NULL)) - return -EINVAL; - - rc = bootenv_get_key_vector(env, &size, 1, &keys); - if (rc != 0) - goto err; - - for (i = 0; i < size; i++) { - key = keys[i]; - rc = bootenv_get(env, key, &val); - if (rc != 0) - goto err; - - wr = fprintf(fp, "%s=%s\n", key, val); - if (wr != strlen(key) + strlen(val) + 2) { - rc = -EIO; - goto err; - } - } - -err: - if (keys != NULL) - free(keys); - return rc; -} - -int -bootenv_valid(bootenv_t env ubi_unused) -{ - /* @FIXME No sanity check implemented. */ - return 0; -} - -int -bootenv_copy_bootenv(bootenv_t in, bootenv_t *out) -{ - int rc = 0; - const char *tmp = NULL; - const char **keys = NULL; - size_t vec_size, i; - - if ((in == NULL) || (out == NULL)) - return -EINVAL; - - /* purge output var for sure... */ - rc = bootenv_destroy(out); - if (rc != 0) - return rc; - - /* create the new map */ - rc = bootenv_create(out); - if (rc != 0) - goto err; - - /* get the key list from the input map */ - rc = bootenv_get_key_vector(in, &vec_size, 0, &keys); - if (rc != 0) - goto err; - - if (vec_size != hashmap_size(in->map)) { - rc = BOOTENV_ECOPY; - goto err; - } - - /* make a deep copy of the hashmap */ - for (i = 0; i < vec_size; i++) { - rc = bootenv_get(in, keys[i], &tmp); - if (rc != 0) - goto err; - - rc = bootenv_set(*out, keys[i], tmp); - if (rc != 0) - goto err; - } - -err: - if (keys != NULL) - free(keys); - - return rc; -} - -/* ------------------------------------------------------------------------- */ - - -int -bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res, - int *warnings, char *err_buf ubi_unused, - size_t err_buf_size ubi_unused) -{ - bootenv_list_t l_old = NULL; - bootenv_list_t l_new = NULL; - const char *pdd_old = NULL; - const char *pdd_new = NULL; - const char *tmp = NULL; - const char **vec_old = NULL; - const char **vec_new = NULL; - const char **pdd_up_vec = NULL; - size_t vec_old_size, vec_new_size, pdd_up_vec_size, i; - int rc = 0; - - if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL)) - return -EINVAL; - - /* get the pdd strings, e.g.: - * pdd_old=a,b,c - * pdd_new=a,c,d,e */ - rc = bootenv_get(env_old, "pdd", &pdd_old); - if (rc != 0) - goto err; - rc = bootenv_get(env_new, "pdd", &pdd_new); - if (rc != 0) - goto err; - - /* put it into a list and then convert it to an vector */ - rc = bootenv_list_create(&l_old); - if (rc != 0) - goto err; - rc = bootenv_list_create(&l_new); - if (rc != 0) - goto err; - - rc = bootenv_list_import(l_old, pdd_old); - if (rc != 0) - goto err; - - rc = bootenv_list_import(l_new, pdd_new); - if (rc != 0) - goto err; - - rc = bootenv_list_to_vector(l_old, &vec_old_size, &vec_old); - if (rc != 0) - goto err; - - rc = bootenv_list_to_vector(l_new, &vec_new_size, &vec_new); - if (rc != 0) - goto err; - - rc = bootenv_copy_bootenv(env_new, env_res); - if (rc != 0) - goto err; - - /* calculate the update vector between the old and new pdd */ - pdd_up_vec = hashmap_get_update_key_vector(vec_old, vec_old_size, - vec_new, vec_new_size, &pdd_up_vec_size); - - if (pdd_up_vec == NULL) { - rc = -ENOMEM; - goto err; - } - - if (pdd_up_vec_size != 0) { - /* need to warn the user about the unset of - * some pdd/bootenv values */ - *warnings = BOOTENV_WPDD_STRING_DIFFERS; - - /* remove all entries in the new bootenv load */ - for (i = 0; i < pdd_up_vec_size; i++) { - bootenv_unset(*env_res, pdd_up_vec[i]); - } - } - - /* generate the keep array and copy old pdd values to new bootenv */ - for (i = 0; i < vec_old_size; i++) { - rc = bootenv_get(env_old, vec_old[i], &tmp); - if (rc != 0) { - rc = BOOTENV_EPDDINVAL; - goto err; - } - rc = bootenv_set(*env_res, vec_old[i], tmp); - if (rc != 0) { - goto err; - } - } - /* put the old pdd string into the result map */ - rc = bootenv_set(*env_res, "pdd", pdd_old); - if (rc != 0) { - goto err; - } - - -err: - if (vec_old != NULL) - free(vec_old); - if (vec_new != NULL) - free(vec_new); - if (pdd_up_vec != NULL) - free(pdd_up_vec); - - bootenv_list_destroy(&l_old); - bootenv_list_destroy(&l_new); - return rc; -} - - -int -bootenv_pdd_overwrite(bootenv_t env_old, bootenv_t env_new, - bootenv_t *env_res, int *warnings ubi_unused, - char *err_buf ubi_unused, size_t err_buf_size ubi_unused) -{ - if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL)) - return -EINVAL; - - return bootenv_copy_bootenv(env_new, env_res); -} - -int -bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new, bootenv_t *env_res, - int *warnings ubi_unused, char *err_buf, size_t err_buf_size) -{ - if ((env_old == NULL) || (env_new == NULL) || (env_res == NULL)) - return -EINVAL; - - snprintf(err_buf, err_buf_size, "The PDD merge operation is not " - "implemented. Contact: <oliloh@de.ibm.com>"); - - return BOOTENV_ENOTIMPL; -} - -/* ------------------------------------------------------------------------- */ - -int -bootenv_get(bootenv_t env, const char *key, const char **value) -{ - if (env == NULL) - return -EINVAL; - - *value = hashmap_lookup(env->map, key); - if (*value == NULL) - return BOOTENV_ENOTFOUND; - - return 0; -} - -int -bootenv_get_num(bootenv_t env, const char *key, uint32_t *value) -{ - char *endptr = NULL; - const char *str; - - if (env == NULL) - return 0; - - str = hashmap_lookup(env->map, key); - if (!str) - return -EINVAL; - - *value = strtoul(str, &endptr, 0); - - if (*endptr == '\0') { - return 0; - } - - return -EINVAL; -} - -int -bootenv_set(bootenv_t env, const char *key, const char *value) -{ - if (env == NULL) - return -EINVAL; - - return hashmap_add(env->map, key, value); -} - -int -bootenv_unset(bootenv_t env, const char *key) -{ - if (env == NULL) - return -EINVAL; - - return hashmap_remove(env->map, key); -} - -int -bootenv_get_key_vector(bootenv_t env, size_t* size, int sort, - const char ***vector) -{ - if ((env == NULL) || (size == NULL)) - return -EINVAL; - - *vector = hashmap_get_key_vector(env->map, size, sort); - - if (*vector == NULL) - return -EINVAL; - - return 0; -} - -int -bootenv_dump(bootenv_t env) -{ - if (env == NULL) - return -EINVAL; - - return hashmap_dump(env->map); -} - -int -bootenv_list_create(bootenv_list_t *list) -{ - bootenv_list_t res; - res = (bootenv_list_t) calloc(1, sizeof(struct bootenv_list)); - - if (res == NULL) - return -ENOMEM; - - res->head = hashmap_new(); - - if (res->head == NULL) { - free(res); - return -ENOMEM; - } - - *list = res; - return 0; -} - -int -bootenv_list_destroy(bootenv_list_t *list) -{ - int rc = 0; - - if (list == NULL) - return -EINVAL; - - bootenv_list_t tmp = *list; - if (tmp == 0) - return 0; - - rc = hashmap_free(tmp->head); - if (rc != 0) - return rc; - - free(tmp); - *list = NULL; - return 0; -} - -int -bootenv_list_import(bootenv_list_t list, const char *str) -{ - if (list == NULL) - return -EINVAL; - - return build_list_definition(list->head, str); -} - -int -bootenv_list_export(bootenv_list_t list, char **string) -{ - size_t size, i, j, bufsize, tmp, rc = 0; - const char **items; - - if (list == NULL) - return -EINVAL; - - bufsize = BOOTENV_MAXLINE; - char *res = (char*) malloc(bufsize * sizeof(char)); - if (res == NULL) - return -ENOMEM; - - rc = bootenv_list_to_vector(list, &size, &items); - if (rc != 0) { - goto err; - } - - j = 0; - for (i = 0; i < size; i++) { - tmp = strlen(items[i]); - if (j >= bufsize) { - bufsize += BOOTENV_MAXLINE; - res = (char*) realloc(res, bufsize * sizeof(char)); - if (res == NULL) { - rc = -ENOMEM; - goto err; - } - } - memcpy(res + j, items[i], tmp); - j += tmp; - if (i < (size - 1)) { - res[j] = ','; - j++; - } - } - j++; - res[j] = '\0'; - free(items); - *string = res; - return 0; -err: - free(items); - return rc; -} - -int -bootenv_list_add(bootenv_list_t list, const char *item) -{ - if ((list == NULL) || (item == NULL)) - return -EINVAL; - - return hashmap_add(list->head, item, ""); -} - -int -bootenv_list_remove(bootenv_list_t list, const char *item) -{ - if ((list == NULL) || (item == NULL)) - return -EINVAL; - - return hashmap_remove(list->head, item); -} - -int -bootenv_list_is_in(bootenv_list_t list, const char *item) -{ - if ((list == NULL) || (item == NULL)) - return -EINVAL; - - return hashmap_lookup(list->head, item) != NULL ? 1 : 0; -} - -int -bootenv_list_to_vector(bootenv_list_t list, size_t *size, const char ***vector) -{ - if ((list == NULL) || (size == NULL)) - return -EINVAL; - - *vector = hashmap_get_key_vector(list->head, size, 1); - if (*vector == NULL) - return -ENOMEM; - - return 0; -} - -int -bootenv_list_to_num_vector(bootenv_list_t list, size_t *size, - uint32_t **vector) -{ - int rc = 0; - size_t i; - uint32_t* res = NULL; - char *endptr = NULL; - const char **a = NULL; - - rc = bootenv_list_to_vector(list, size, &a); - if (rc != 0) - goto err; - - res = (uint32_t*) malloc (*size * sizeof(uint32_t)); - if (!res) - goto err; - - for (i = 0; i < *size; i++) { - res[i] = strtoul(a[i], &endptr, 0); - if (*endptr != '\0') - goto err; - } - - if (a) - free(a); - *vector = res; - return 0; - -err: - if (a) - free(a); - if (res) - free(res); - return rc; -} diff --git a/ubi-utils/src/bootenv.h b/ubi-utils/src/bootenv.h deleted file mode 100644 index 8fecdbf..0000000 --- a/ubi-utils/src/bootenv.h +++ /dev/null @@ -1,434 +0,0 @@ -#ifndef __BOOTENV_H__ -#define __BOOTENV_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdio.h> /* FILE */ -#include <stdint.h> -#include <pfiflash.h> - -/* DOXYGEN DOCUMENTATION */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file bootenv.h - * @author oliloh@de.ibm.com - * @version 1.3 - * - * 1.3 Some renaming - */ - -/** - * @mainpage Usage - * - * @section intro Introduction - * This library provides all functionality to handle with the so-called - * platform description data (PDD) and the bootparameters defined in - * U-Boot. It is able to apply the defined PDD operations in PDD update - * scenarios. For more information about the PDD and bootparameter - * environment "bootenv" confer the PDD documentation. - * - * @section ret Return codes - * This library defines some return codes which will be delivered classified - * as warnings or errors. See the "Defines" section for details and numeric - * values. - * - * @section benv Bootenv format description - * There are two different input formats: - * - text files - * - binary files - * - * @subsection txt Text Files - * Text files have to be specified like: - * @verbatim key1=value1,value2,value7\n key2=value55,value1\n key4=value1\n@endverbatim - * - * @subsection bin Binary files - * Binary files have to be specified like: - * @verbatim<CRC32-bit>key1=value1,value2,value7\0key2=value55,value1\0... @endverbatim - * You can confer the U-Boot documentation for more details. - * - * @section benvlists Bootenv lists format description. - * Values referenced in the preceeding subsection can be - * defined like lists: - * @verbatim value1,value2,value3 @endverbatim - * There are some situation where a conversion of a comma - * seperated list can be useful, e.g. to get a list - * of defined PDD entries. - */ - -#define BOOTENV_MAXSIZE (1024 * 100) /* max 100kiB space for bootenv */ - -/** - * @def BOOTENV_ECRC - * @brief Given binary file is to large. - * @def BOOTENV_EFMT - * @brief Given bootenv section has an invalid format - * @def BOOTENV_EBADENTRY - * @brief Bad entry in the bootenv section. - * @def BOOTENV_EINVAL - * @brief Invalid bootenv defintion. - * @def BOOTENV_ENOPDD - * @brief Given bootenv sectoin has no PDD defintion string (pdd=...). - * @def BOOTENV_EPDDINVAL - * @brief Given bootenv section has an invalid PDD defintion. - * @def BOOTENV_ENOTIMPL - * @brief Functionality not implemented. - * @def BOOTENV_ECOPY - * @brief Bootenv memory copy error - * @def BOOTENV_ENOTFOUND - * @brief Given key has has no value. - * @def BOOTENV_EMAX - * @brief Highest error value. - */ -#define BOOTENV_ETOOBIG 1 -#define BOOTENV_EFMT 2 -#define BOOTENV_EBADENTRY 3 -#define BOOTENV_EINVAL 4 -#define BOOTENV_ENOPDD 5 -#define BOOTENV_EPDDINVAL 6 -#define BOOTENV_ENOTIMPL 7 -#define BOOTENV_ECOPY 8 -#define BOOTENV_ENOTFOUND 9 -#define BOOTENV_EMAX 10 - -/** - * @def BOOTENV_W - * @brief A warning which is handled internally as an error - * but can be recovered by manual effort. - * @def BOOTENV_WPDD_STRING_DIFFERS - * @brief The PDD strings of old and new PDD differ and - * can cause update problems, because new PDD values - * are removed from the bootenv section completely. - */ -#define BOOTENV_W 20 -#define BOOTENV_WPDD_STRING_DIFFERS 21 -#define BOOTENV_WMAX 22 /* highest warning value */ - - -typedef struct bootenv *bootenv_t; - /**< A bootenv library handle. */ - -typedef struct bootenv_list *bootenv_list_t; - /**< A handle for a value list. */ - -typedef int(*pdd_func_t)(bootenv_t, bootenv_t, bootenv_t*, - int*, char*, size_t); - - -/** - * @brief Get a new handle. - * @return 0 - * @return or error - * */ -int bootenv_create(bootenv_t *env); - -/** - * @brief Cleanup structure. - * @param env Bootenv structure which shall be destroyed. - * @return 0 - * @return or error - */ -int bootenv_destroy(bootenv_t *env); - -/** - * @brief Copy a bootenv handle. - * @param in The input bootenv. - * @param out The copied output bootenv. Discards old data. - * @return 0 - * @return or error - */ -int bootenv_copy_bootenv(bootenv_t in, bootenv_t *out); - -/** - * @brief Looks for a value inside the bootenv data. - * @param env Handle to a bootenv structure. - * @param key The key. - * @return NULL key not found - * @return !NULL ptr to value - */ -int bootenv_get(bootenv_t env, const char *key, const char **value); - - -/** - * @brief Looks for a value inside the bootenv data and converts it to num. - * @param env Handle to a bootenv structure. - * @param key The key. - * @param value A pointer to the resulting numerical value - * @return NULL key not found - * @return !NULL ptr to value - */ -int bootenv_get_num(bootenv_t env, const char *key, uint32_t *value); - -/** - * @brief Set a bootenv value by key. - * @param env Handle to a bootenv structure. - * @param key Key. - * @param value Value to set. - * @return 0 - * @return or error - */ -int bootenv_set(bootenv_t env, const char *key, const char *value); - -/** - * @brief Remove the given key (and its value) from a bootenv structure. - * @param env Handle to a bootenv structure. - * @param key Key. - * @return 0 - * @return or error - */ -int bootenv_unset(bootenv_t env, const char *key); - - -/** - * @brief Get a vector of all keys which are currently set - * within a bootenv handle. - * @param env Handle to a bootenv structure. - * @param size The size of the allocated array structure. - * @param sort Flag, if set the vector is sorted ascending. - * @return NULL on error. - * @return !NULL a pointer to the first element the allocated vector. - * @warning Free the allocate memory yourself! - */ -int bootenv_get_key_vector(bootenv_t env, size_t *size, int sort, - const char ***vector); - -/** - * @brief Calculate the size in bytes which are necessary to write the - * current bootenv section in a *binary file. - * @param env bootenv handle. - * @param size The size in bytes of the bootenv handle. - * @return 0 - * @return or ERROR. - */ -int bootenv_size(bootenv_t env, size_t *size); - -/** - * @brief Read a binary bootenv file. - * @param fp File pointer to input stream. - * @param env bootenv handle. - * @param size maximum data size. - * @return 0 - * @return or ERROR. - */ -int bootenv_read(FILE* fp, bootenv_t env, size_t size); - -/** - * @param ret_crc return value of crc of read data - */ -int bootenv_read_crc(FILE* fp, bootenv_t env, size_t size, uint32_t *ret_crc); - -/** - * @brief Read bootenv data from an text/ascii file. - * @param fp File pointer to ascii PDD file. - * @param env bootenv handle - * @return 0 - * @return or ERROR. - */ -int bootenv_read_txt(FILE* fp, bootenv_t env); - -/** - * @brief Write a bootenv structure to the given location (binary). - * @param fp Filepointer to binary file. - * @param env Bootenv structure which shall be written. - * @return 0 - * @return or error - */ -int bootenv_write(FILE* fp, bootenv_t env); - -/** - * @param ret_crc return value of crc of read data - */ -int bootenv_write_crc(FILE* fp, bootenv_t env, uint32_t* ret_crc); - -/** - * @brief Write a bootenv structure to the given location (text). - * @param fp Filepointer to text file. - * @param env Bootenv structure which shall be written. - * @return 0 - * @return or error - */ -int bootenv_write_txt(FILE* fp, bootenv_t env); - -/** - * @brief Compare bootenvs using memcmp(). - * @param first First bootenv. - * @param second Second bootenv. - * @return 0 if bootenvs are equal - * @return < 0 if error - * @return > 0 if unequal - */ -int bootenv_compare(bootenv_t first, bootenv_t second); - -/** - * @brief Prototype for a PDD handling funtion - */ - -/** - * @brief The PDD keep operation. - * @param env_old The old bootenv structure. - * @param env_new The new bootenv structure. - * @param env_res The result of PDD keep. - * @param warnings A flag which marks any warnings. - * @return 0 - * @return or error - * @note For a complete documentation about the algorithm confer the - * PDD documentation. - */ -int bootenv_pdd_keep(bootenv_t env_old, bootenv_t env_new, - bootenv_t *env_res, int *warnings, - char *err_buf, size_t err_buf_size); - - -/** - * @brief The PDD merge operation. - * @param env_old The old bootenv structure. - * @param env_new The new bootenv structure. - * @param env_res The result of merge-pdd. - * @param warnings A flag which marks any warnings. - * @return 0 - * @return or error - * @note For a complete documentation about the algorithm confer the - * PDD documentation. - */ -int bootenv_pdd_merge(bootenv_t env_old, bootenv_t env_new, - bootenv_t *env_res, int *warnings, - char *err_buf, size_t err_buf_size); - -/** - * @brief The PDD overwrite operation. - * @param env_old The old bootenv structure. - * @param env_new The new bootenv structure. - * @param env_res The result of overwrite-pdd. - * @param warnings A flag which marks any warnings. - * @return 0 - * @return or error - * @note For a complete documentation about the algorithm confer the - * PDD documentation. - */ -int bootenv_pdd_overwrite(bootenv_t env_new, - bootenv_t env_old, bootenv_t *env_res, int *warnings, - char *err_buf, size_t err_buf_size); - -/** - * @brief Dump a bootenv structure to stdout. (Debug) - * @param env Handle to a bootenv structure. - * @return 0 - * @return or error - */ -int bootenv_dump(bootenv_t env); - -/** - * @brief Validate a bootenv structure. - * @param env Handle to a bootenv structure. - * @return 0 - * @return or error - */ -int bootenv_valid(bootenv_t env); - -/** - * @brief Create a new bootenv list structure. - * @return NULL on error - * @return or a new list handle. - * @note This structure is used to store values in a list. - * A useful addition when handling PDD strings. - */ -int bootenv_list_create(bootenv_list_t *list); - -/** - * @brief Destroy a bootenv list structure - * @param list Handle to a bootenv list structure. - * @return 0 - * @return or error - */ -int bootenv_list_destroy(bootenv_list_t *list); - -/** - * @brief Import a list from a comma seperated string - * @param list Handle to a bootenv list structure. - * @param str Comma seperated string list. - * @return 0 - * @return or error - */ -int bootenv_list_import(bootenv_list_t list, const char *str); - -/** - * @brief Export a list to a string of comma seperated values. - * @param list Handle to a bootenv list structure. - * @return NULL one error - * @return or pointer to a newly allocated string. - * @warning Free the allocated memory by yourself! - */ -int bootenv_list_export(bootenv_list_t list, char **string); - -/** - * @brief Add an item to the list. - * @param list A handle of a list structure. - * @param item An item. - * @return 0 - * @return or error - */ -int bootenv_list_add(bootenv_list_t list, const char *item); - -/** - * @brief Remove an item from the list. - * @param list A handle of a list structure. - * @param item An item. - * @return 0 - * @return or error - */ -int bootenv_list_remove(bootenv_list_t list, const char *item); - -/** - * @brief Check if a given item is in a given list. - * @param list A handle of a list structure. - * @param item An item. - * @return 1 Item is in list. - * @return 0 Item is not in list. - */ -int bootenv_list_is_in(bootenv_list_t list, const char *item); - - -/** - * @brief Convert a list into a vector of all values inside the list. - * @param list Handle to a bootenv structure. - * @param size The size of the allocated vector structure. - * @return 0 - * @return or error - * @warning Free the allocate memory yourself! - */ -int bootenv_list_to_vector(bootenv_list_t list, size_t *size, - const char ***vector); - -/** - * @brief Convert a list into a vector of all values inside the list. - * @param list Handle to a bootenv structure. - * @param size The size of the allocated vector structure. - * @return 0 - * @return or error - * @warning Free the allocate memory yourself! - */ -int bootenv_list_to_num_vector(bootenv_list_t list, size_t *size, - uint32_t **vector); - -#ifdef __cplusplus -} -#endif -#endif /*__BOOTENV_H__ */ diff --git a/ubi-utils/src/common.c b/ubi-utils/src/common.c index f8110c3..56244df 100644 --- a/ubi-utils/src/common.c +++ b/ubi-utils/src/common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) Artem Bityutskiy, 2007 + * Copyright (C) 2007, 2008 Nokia Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,11 +19,13 @@ /* * This file contains various common stuff used by UBI utilities. * - * Author: Artem Bityutskiy + * Authors: Artem Bityutskiy + * Adrian Hunter */ #include <stdio.h> #include <string.h> +#include <ctype.h> /** * ubiutils_bytes_multiplier - convert size specifier to an integer @@ -87,3 +89,56 @@ void ubiutils_print_bytes(long long bytes, int bracket) if (bracket) printf(")"); } + +/** + * ubiutils_print_text - print text and fold it. + * @stream: file stream to print to + * @text: text to print + * @width: maximum allowed text width + * + * Print text and fold it so that each line would not have more then @width + * characters. + */ +void ubiutils_print_text(FILE *stream, const char *text, int width) +{ + int pos, bpos = 0; + const char *p; + char line[1024]; + + if (width > 1023) { + fprintf(stream, "%s\n", text); + return; + } + p = text; + pos = 0; + while (p[pos]) { + while (!isspace(p[pos])) { + line[pos] = p[pos]; + if (!p[pos]) + break; + ++pos; + if (pos == width) { + line[pos] = '\0'; + fprintf(stream, "%s\n", line); + p += pos; + pos = 0; + } + } + while (pos < width) { + line[pos] = p[pos]; + if (!p[pos]) { + bpos = pos; + break; + } + if (isspace(p[pos])) + bpos = pos; + ++pos; + } + line[bpos] = '\0'; + fprintf(stream, "%s\n", line); + p += bpos; + pos = 0; + while (p[pos] && isspace(p[pos])) + ++p; + } +} diff --git a/ubi-utils/src/common.h b/ubi-utils/src/common.h index 89094ab..3ee93ff 100644 --- a/ubi-utils/src/common.h +++ b/ubi-utils/src/common.h @@ -19,6 +19,8 @@ #ifndef __UBI_UTILS_COMMON_H__ #define __UBI_UTILS_COMMON_H__ +#include <stdio.h> + #ifdef __cplusplus extern "C" { #endif @@ -26,18 +28,30 @@ extern "C" { #define MIN(a ,b) ((a) < (b) ? (a) : (b)) #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +/* Verbose messages */ +#define verbose(verbose, fmt, ...) do { \ + if (verbose) \ + printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \ +} while(0) + +/* Normal messages */ +#define normsg(fmt, ...) do { \ + printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \ +} while(0) + /* Error messages */ #define errmsg(fmt, ...) do { \ - fprintf(stderr, PROGRAM_NAME " error: " fmt "\n", ##__VA_ARGS__); \ + fprintf(stderr, PROGRAM_NAME " error: " fmt "\n", ##__VA_ARGS__); \ } while(0) /* Warnings */ #define warnmsg(fmt, ...) do { \ - fprintf(stderr, PROGRAM_NAME " warning: " fmt "\n", ##__VA_ARGS__); \ + fprintf(stderr, PROGRAM_NAME " warning: " fmt "\n", ##__VA_ARGS__); \ } while(0) int ubiutils_get_multiplier(const char *str); void ubiutils_print_bytes(long long bytes, int bracket); +void ubiutils_print_text(FILE *stream, const char *txt, int len); #ifdef __cplusplus } diff --git a/ubi-utils/src/config.h b/ubi-utils/src/config.h deleted file mode 100644 index 55e60f3..0000000 --- a/ubi-utils/src/config.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __CONFIG_H__ -#define __CONFIG_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Frank Haverkamp - */ - -#define PACKAGE_BUGREPORT \ - "haver@vnet.ibm.com, dedekind@linutronix.de, or tglx@linutronix.de" - -#define ubi_unused __attribute__((unused)) - -#endif diff --git a/ubi-utils/src/dictionary.c b/ubi-utils/src/dictionary.c new file mode 100644 index 0000000..b7c9ebf --- /dev/null +++ b/ubi-utils/src/dictionary.c @@ -0,0 +1,405 @@ +/*-------------------------------------------------------------------------*/ +/** + @file dictionary.c + @author N. Devillard + @date Sep 2007 + @version $Revision: 1.27 $ + @brief Implements a dictionary for string variables. + + This module implements a simple dictionary object, i.e. a list + of string/string associations. This object is useful to store e.g. + informations retrieved from a configuration file (ini files). +*/ +/*--------------------------------------------------------------------------*/ + +/* + $Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $ + $Revision: 1.27 $ +*/ +/*--------------------------------------------------------------------------- + Includes + ---------------------------------------------------------------------------*/ +#include "dictionary.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/** Maximum value size for integers and doubles. */ +#define MAXVALSZ 1024 + +/** Minimal allocated number of entries in a dictionary */ +#define DICTMINSZ 128 + +/** Invalid key token */ +#define DICT_INVALID_KEY ((char*)-1) + +/*--------------------------------------------------------------------------- + Private functions + ---------------------------------------------------------------------------*/ + +/* Doubles the allocated size associated to a pointer */ +/* 'size' is the current allocated size. */ +static void * mem_double(void * ptr, int size) +{ + void * newptr ; + + newptr = calloc(2*size, 1); + if (newptr==NULL) { + return NULL ; + } + memcpy(newptr, ptr, size); + free(ptr); + return newptr ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Duplicate a string + @param s String to duplicate + @return Pointer to a newly allocated string, to be freed with free() + + This is a replacement for strdup(). This implementation is provided + for systems that do not have it. + */ +/*--------------------------------------------------------------------------*/ +static char * xstrdup(char * s) +{ + char * t ; + if (!s) + return NULL ; + t = malloc(strlen(s)+1) ; + if (t) { + strcpy(t,s); + } + return t ; +} + +/*--------------------------------------------------------------------------- + Function codes + ---------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------*/ +/** + @brief Compute the hash key for a string. + @param key Character string to use for key. + @return 1 unsigned int on at least 32 bits. + + This hash function has been taken from an Article in Dr Dobbs Journal. + This is normally a collision-free function, distributing keys evenly. + The key is stored anyway in the struct so that collision can be avoided + by comparing the key itself in last resort. + */ +/*--------------------------------------------------------------------------*/ +unsigned dictionary_hash(char * key) +{ + int len ; + unsigned hash ; + int i ; + + len = strlen(key); + for (hash=0, i=0 ; i<len ; i++) { + hash += (unsigned)key[i] ; + hash += (hash<<10); + hash ^= (hash>>6) ; + } + hash += (hash <<3); + hash ^= (hash >>11); + hash += (hash <<15); + return hash ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Create a new dictionary object. + @param size Optional initial size of the dictionary. + @return 1 newly allocated dictionary objet. + + This function allocates a new dictionary object of given size and returns + it. If you do not know in advance (roughly) the number of entries in the + dictionary, give size=0. + */ +/*--------------------------------------------------------------------------*/ +dictionary * dictionary_new(int size) +{ + dictionary * d ; + + /* If no size was specified, allocate space for DICTMINSZ */ + if (size<DICTMINSZ) size=DICTMINSZ ; + + if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) { + return NULL; + } + d->size = size ; + d->val = (char **)calloc(size, sizeof(char*)); + d->key = (char **)calloc(size, sizeof(char*)); + d->hash = (unsigned int *)calloc(size, sizeof(unsigned)); + return d ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a dictionary object + @param d dictionary object to deallocate. + @return void + + Deallocate a dictionary object and all memory associated to it. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_del(dictionary * d) +{ + int i ; + + if (d==NULL) return ; + for (i=0 ; i<d->size ; i++) { + if (d->key[i]!=NULL) + free(d->key[i]); + if (d->val[i]!=NULL) + free(d->val[i]); + } + free(d->val); + free(d->key); + free(d->hash); + free(d); + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get a value from a dictionary. + @param d dictionary object to search. + @param key Key to look for in the dictionary. + @param def Default value to return if key not found. + @return 1 pointer to internally allocated character string. + + This function locates a key in a dictionary and returns a pointer to its + value, or the passed 'def' pointer if no such key can be found in + dictionary. The returned character pointer points to data internal to the + dictionary object, you should not try to free it or modify it. + */ +/*--------------------------------------------------------------------------*/ +char * dictionary_get(dictionary * d, char * key, char * def) +{ + unsigned hash ; + int i ; + + hash = dictionary_hash(key); + for (i=0 ; i<d->size ; i++) { + if (d->key[i]==NULL) + continue ; + /* Compare hash */ + if (hash==d->hash[i]) { + /* Compare string, to avoid hash collisions */ + if (!strcmp(key, d->key[i])) { + return d->val[i] ; + } + } + } + return def ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Set a value in a dictionary. + @param d dictionary object to modify. + @param key Key to modify or add. + @param val Value to add. + @return int 0 if Ok, anything else otherwise + + If the given key is found in the dictionary, the associated value is + replaced by the provided one. If the key cannot be found in the + dictionary, it is added to it. + + It is Ok to provide a NULL value for val, but NULL values for the dictionary + or the key are considered as errors: the function will return immediately + in such a case. + + Notice that if you dictionary_set a variable to NULL, a call to + dictionary_get will return a NULL value: the variable will be found, and + its value (NULL) is returned. In other words, setting the variable + content to NULL is equivalent to deleting the variable from the + dictionary. It is not possible (in this implementation) to have a key in + the dictionary without value. + + This function returns non-zero in case of failure. + */ +/*--------------------------------------------------------------------------*/ +int dictionary_set(dictionary * d, char * key, char * val) +{ + int i ; + unsigned hash ; + + if (d==NULL || key==NULL) return -1 ; + + /* Compute hash for this key */ + hash = dictionary_hash(key) ; + /* Find if value is already in dictionary */ + if (d->n>0) { + for (i=0 ; i<d->size ; i++) { + if (d->key[i]==NULL) + continue ; + if (hash==d->hash[i]) { /* Same hash value */ + if (!strcmp(key, d->key[i])) { /* Same key */ + /* Found a value: modify and return */ + if (d->val[i]!=NULL) + free(d->val[i]); + d->val[i] = val ? xstrdup(val) : NULL ; + /* Value has been modified: return */ + return 0 ; + } + } + } + } + /* Add a new value */ + /* See if dictionary needs to grow */ + if (d->n==d->size) { + + /* Reached maximum size: reallocate dictionary */ + d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ; + d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ; + d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ; + if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) { + /* Cannot grow dictionary */ + return -1 ; + } + /* Double size */ + d->size *= 2 ; + } + + /* Insert key in the first empty slot */ + for (i=0 ; i<d->size ; i++) { + if (d->key[i]==NULL) { + /* Add key here */ + break ; + } + } + /* Copy key */ + d->key[i] = xstrdup(key); + d->val[i] = val ? xstrdup(val) : NULL ; + d->hash[i] = hash; + d->n ++ ; + return 0 ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a key in a dictionary + @param d dictionary object to modify. + @param key Key to remove. + @return void + + This function deletes a key in a dictionary. Nothing is done if the + key cannot be found. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_unset(dictionary * d, char * key) +{ + unsigned hash ; + int i ; + + if (key == NULL) { + return; + } + + hash = dictionary_hash(key); + for (i=0 ; i<d->size ; i++) { + if (d->key[i]==NULL) + continue ; + /* Compare hash */ + if (hash==d->hash[i]) { + /* Compare string, to avoid hash collisions */ + if (!strcmp(key, d->key[i])) { + /* Found key */ + break ; + } + } + } + if (i>=d->size) + /* Key not found */ + return ; + + free(d->key[i]); + d->key[i] = NULL ; + if (d->val[i]!=NULL) { + free(d->val[i]); + d->val[i] = NULL ; + } + d->hash[i] = 0 ; + d->n -- ; + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump + @param f Opened file pointer. + @return void + + Dumps a dictionary onto an opened file pointer. Key pairs are printed out + as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as + output file pointers. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_dump(dictionary * d, FILE * out) +{ + int i ; + + if (d==NULL || out==NULL) return ; + if (d->n<1) { + fprintf(out, "empty dictionary\n"); + return ; + } + for (i=0 ; i<d->size ; i++) { + if (d->key[i]) { + fprintf(out, "%20s\t[%s]\n", + d->key[i], + d->val[i] ? d->val[i] : "UNDEF"); + } + } + return ; +} + + +/* Test code */ +#ifdef TESTDIC +#define NVALS 20000 +int main(int argc, char *argv[]) +{ + dictionary * d ; + char * val ; + int i ; + char cval[90] ; + + /* Allocate dictionary */ + printf("allocating...\n"); + d = dictionary_new(0); + + /* Set values in dictionary */ + printf("setting %d values...\n", NVALS); + for (i=0 ; i<NVALS ; i++) { + sprintf(cval, "%04d", i); + dictionary_set(d, cval, "salut"); + } + printf("getting %d values...\n", NVALS); + for (i=0 ; i<NVALS ; i++) { + sprintf(cval, "%04d", i); + val = dictionary_get(d, cval, DICT_INVALID_KEY); + if (val==DICT_INVALID_KEY) { + printf("cannot get value for key [%s]\n", cval); + } + } + printf("unsetting %d values...\n", NVALS); + for (i=0 ; i<NVALS ; i++) { + sprintf(cval, "%04d", i); + dictionary_unset(d, cval); + } + if (d->n != 0) { + printf("error deleting values\n"); + } + printf("deallocating...\n"); + dictionary_del(d); + return 0 ; +} +#endif +/* vim: set ts=4 et sw=4 tw=75 */ diff --git a/ubi-utils/src/dictionary.h b/ubi-utils/src/dictionary.h new file mode 100644 index 0000000..c7d1790 --- /dev/null +++ b/ubi-utils/src/dictionary.h @@ -0,0 +1,174 @@ + +/*-------------------------------------------------------------------------*/ +/** + @file dictionary.h + @author N. Devillard + @date Sep 2007 + @version $Revision: 1.12 $ + @brief Implements a dictionary for string variables. + + This module implements a simple dictionary object, i.e. a list + of string/string associations. This object is useful to store e.g. + informations retrieved from a configuration file (ini files). +*/ +/*--------------------------------------------------------------------------*/ + +/* + $Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $ + $Author: ndevilla $ + $Date: 2007-11-23 21:37:00 $ + $Revision: 1.12 $ +*/ + +#ifndef _DICTIONARY_H_ +#define _DICTIONARY_H_ + +/*--------------------------------------------------------------------------- + Includes + ---------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/*--------------------------------------------------------------------------- + New types + ---------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------*/ +/** + @brief Dictionary object + + This object contains a list of string/string associations. Each + association is identified by a unique string key. Looking up values + in the dictionary is speeded up by the use of a (hopefully collision-free) + hash function. + */ +/*-------------------------------------------------------------------------*/ +typedef struct _dictionary_ { + int n ; /** Number of entries in dictionary */ + int size ; /** Storage size */ + char ** val ; /** List of string values */ + char ** key ; /** List of string keys */ + unsigned * hash ; /** List of hash values for keys */ +} dictionary ; + + +/*--------------------------------------------------------------------------- + Function prototypes + ---------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------*/ +/** + @brief Compute the hash key for a string. + @param key Character string to use for key. + @return 1 unsigned int on at least 32 bits. + + This hash function has been taken from an Article in Dr Dobbs Journal. + This is normally a collision-free function, distributing keys evenly. + The key is stored anyway in the struct so that collision can be avoided + by comparing the key itself in last resort. + */ +/*--------------------------------------------------------------------------*/ +unsigned dictionary_hash(char * key); + +/*-------------------------------------------------------------------------*/ +/** + @brief Create a new dictionary object. + @param size Optional initial size of the dictionary. + @return 1 newly allocated dictionary objet. + + This function allocates a new dictionary object of given size and returns + it. If you do not know in advance (roughly) the number of entries in the + dictionary, give size=0. + */ +/*--------------------------------------------------------------------------*/ +dictionary * dictionary_new(int size); + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a dictionary object + @param d dictionary object to deallocate. + @return void + + Deallocate a dictionary object and all memory associated to it. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_del(dictionary * vd); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get a value from a dictionary. + @param d dictionary object to search. + @param key Key to look for in the dictionary. + @param def Default value to return if key not found. + @return 1 pointer to internally allocated character string. + + This function locates a key in a dictionary and returns a pointer to its + value, or the passed 'def' pointer if no such key can be found in + dictionary. The returned character pointer points to data internal to the + dictionary object, you should not try to free it or modify it. + */ +/*--------------------------------------------------------------------------*/ +char * dictionary_get(dictionary * d, char * key, char * def); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Set a value in a dictionary. + @param d dictionary object to modify. + @param key Key to modify or add. + @param val Value to add. + @return int 0 if Ok, anything else otherwise + + If the given key is found in the dictionary, the associated value is + replaced by the provided one. If the key cannot be found in the + dictionary, it is added to it. + + It is Ok to provide a NULL value for val, but NULL values for the dictionary + or the key are considered as errors: the function will return immediately + in such a case. + + Notice that if you dictionary_set a variable to NULL, a call to + dictionary_get will return a NULL value: the variable will be found, and + its value (NULL) is returned. In other words, setting the variable + content to NULL is equivalent to deleting the variable from the + dictionary. It is not possible (in this implementation) to have a key in + the dictionary without value. + + This function returns non-zero in case of failure. + */ +/*--------------------------------------------------------------------------*/ +int dictionary_set(dictionary * vd, char * key, char * val); + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a key in a dictionary + @param d dictionary object to modify. + @param key Key to remove. + @return void + + This function deletes a key in a dictionary. Nothing is done if the + key cannot be found. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_unset(dictionary * d, char * key); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump + @param f Opened file pointer. + @return void + + Dumps a dictionary onto an opened file pointer. Key pairs are printed out + as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as + output file pointers. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_dump(dictionary * d, FILE * out); + +#endif diff --git a/ubi-utils/src/eb_chain.c b/ubi-utils/src/eb_chain.c deleted file mode 100644 index a018ae6..0000000 --- a/ubi-utils/src/eb_chain.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006, 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Author: Drake Dowsett, dowsett@de.ibm.com - * Contact: Andreas Arnez, arnez@de.ibm.com - */ - -/* see eb_chain.h */ - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include "unubi_analyze.h" -#include "crc32.h" - -#define COPY(dst, src) \ - do { \ - dst = malloc(sizeof(*dst)); \ - if (dst == NULL) \ - return -ENOMEM; \ - memcpy(dst, src, sizeof(*dst)); \ - } while (0) - - -/** - * inserts an eb_info into the chain starting at head, then searching - * linearly for the correct position; - * new should contain valid vid and ec headers and the data_crc should - * already have been checked before insertion, otherwise the chain - * could be have un an undesired manner; - * returns -ENOMEM if alloc fails, otherwise SHOULD always return 0, - * if not, the code reached the last line and returned -EAGAIN, - * meaning there is a bug or a case not being handled here; - **/ -int -eb_chain_insert(struct eb_info **head, struct eb_info *new) -{ - uint32_t vol, num, ver; - uint32_t new_vol, new_num, new_ver; - struct eb_info *prev, *cur, *hist, *ins; - struct eb_info **prev_ptr; - - if ((head == NULL) || (new == NULL)) - return 0; - - if (*head == NULL) { - COPY(*head, new); - (*head)->next = NULL; - return 0; - } - - new_vol = __be32_to_cpu(new->vid.vol_id); - new_num = __be32_to_cpu(new->vid.lnum); - new_ver = __be32_to_cpu(new->vid.leb_ver); - - /** TRAVERSE HORIZONTALY **/ - - cur = *head; - prev = NULL; - - /* traverse until vol_id/lnum align */ - vol = __be32_to_cpu(cur->vid.vol_id); - num = __be32_to_cpu(cur->vid.lnum); - while ((new_vol > vol) || ((new_vol == vol) && (new_num > num))) { - /* insert new at end of chain */ - if (cur->next == NULL) { - COPY(ins, new); - ins->next = NULL; - cur->next = ins; - return 0; - } - - prev = cur; - cur = cur->next; - vol = __be32_to_cpu(cur->vid.vol_id); - num = __be32_to_cpu(cur->vid.lnum); - } - - if (prev == NULL) - prev_ptr = head; - else - prev_ptr = &(prev->next); - - /* insert new into the middle of chain */ - if ((new_vol != vol) || (new_num != num)) { - COPY(ins, new); - ins->next = cur; - *prev_ptr = ins; - return 0; - } - - /** TRAVERSE VERTICALY **/ - - hist = cur; - prev = NULL; - - /* traverse until versions align */ - ver = __be32_to_cpu(cur->vid.leb_ver); - while (new_ver < ver) { - /* insert new at bottom of history */ - if (hist->older == NULL) { - COPY(ins, new); - ins->next = NULL; - ins->older = NULL; - hist->older = ins; - return 0; - } - - prev = hist; - hist = hist->older; - ver = __be32_to_cpu(hist->vid.leb_ver); - } - - if (prev == NULL) { - /* replace active version */ - COPY(ins, new); - ins->next = hist->next; - *prev_ptr = ins; - - /* place cur in vertical histroy */ - ins->older = hist; - hist->next = NULL; - return 0; - } - - /* insert between versions, beneath active version */ - COPY(ins, new); - ins->next = NULL; - ins->older = prev->older; - prev->older = ins; - return 0; -} - - -/** - * sets the pointer at pos to the position of the first entry in the chain - * with of vol_id and, if given, with the same lnum as *lnum; - * if there is no entry in the chain, then *pos is NULL on return; - * always returns 0; - **/ -int -eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum, - struct eb_info **pos) -{ - uint32_t vol, num; - struct eb_info *cur; - - if ((head == NULL) || (*head == NULL) || (pos == NULL)) - return 0; - - *pos = NULL; - - cur = *head; - while (cur != NULL) { - vol = __be32_to_cpu(cur->vid.vol_id); - num = __be32_to_cpu(cur->vid.lnum); - - if ((vol_id == vol) && ((lnum == NULL) || (*lnum == num))) { - *pos = cur; - return 0; - } - - cur = cur->next; - } - - return 0; -} - - -/** - * prints to stream, the vol_id, lnum and leb_ver for each entry in the - * chain, starting at head; - * this is intended for debuging purposes; - * always returns 0; - * - * FIXME I do not like the double list traversion ... - **/ -int -eb_chain_print(FILE* stream, struct eb_info *head) -{ - struct eb_info *cur; - - if (stream == NULL) - stream = stdout; - - if (head == NULL) { - fprintf(stream, "EMPTY\n"); - return 0; - } - /* 012345678012345678012345678012301230123 0123 01234567 0123457 01234567*/ - fprintf(stream, "VOL_ID LNUM LEB_VER EC VID DAT PBLK PADDR DSIZE EC\n"); - cur = head; - while (cur != NULL) { - struct eb_info *hist; - - fprintf(stream, "%08x %-8u %08x %-4s%-4s", - __be32_to_cpu(cur->vid.vol_id), - __be32_to_cpu(cur->vid.lnum), - __be32_to_cpu(cur->vid.leb_ver), - cur->ec_crc_ok ? "ok":"bad", - cur->vid_crc_ok ? "ok":"bad"); - if (cur->vid.vol_type == UBI_VID_STATIC) - fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"bad"); - else fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"ign"); - fprintf(stream, " %-4d %08x %-8u %-8llu\n", cur->phys_block, - cur->phys_addr, __be32_to_cpu(cur->vid.data_size), - __be64_to_cpu(cur->ec.ec)); - - hist = cur->older; - while (hist != NULL) { - fprintf(stream, "%08x %-8u %08x %-4s%-4s", - __be32_to_cpu(hist->vid.vol_id), - __be32_to_cpu(hist->vid.lnum), - __be32_to_cpu(hist->vid.leb_ver), - hist->ec_crc_ok ? "ok":"bad", - hist->vid_crc_ok ? "ok":"bad"); - if (hist->vid.vol_type == UBI_VID_STATIC) - fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"bad"); - else fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"ign"); - fprintf(stream, " %-4d %08x %-8u %-8llu (*)\n", - hist->phys_block, hist->phys_addr, - __be32_to_cpu(hist->vid.data_size), - __be64_to_cpu(hist->ec.ec)); - - hist = hist->older; - } - cur = cur->next; - } - - return 0; -} - - -/** - * frees the memory of the entire chain, starting at head; - * head will be NULL on return; - * always returns 0; - **/ -int -eb_chain_destroy(struct eb_info **head) -{ - if (head == NULL) - return 0; - - while (*head != NULL) { - struct eb_info *cur; - struct eb_info *hist; - - cur = *head; - *head = (*head)->next; - - hist = cur->older; - while (hist != NULL) { - struct eb_info *temp; - - temp = hist; - hist = hist->older; - free(temp); - } - free(cur); - } - return 0; -} - diff --git a/ubi-utils/src/example_ubi.h b/ubi-utils/src/example_ubi.h deleted file mode 100644 index 23c7b54..0000000 --- a/ubi-utils/src/example_ubi.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __EXAMPLE_UBI_H__ -#define __EXAMPLE_UBI_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * Defaults for our cards. - */ -#define EXAMPLE_UBI_DEVICE 0 -#define EXAMPLE_BOOTENV_VOL_ID_1 4 -#define EXAMPLE_BOOTENV_VOL_ID_2 5 - -#endif /* __EXAMPLE_UBI_H__ */ diff --git a/ubi-utils/src/hashmap.c b/ubi-utils/src/hashmap.c deleted file mode 100644 index 3511d56..0000000 --- a/ubi-utils/src/hashmap.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -#include <errno.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include "error.h" -#include "hashmap.h" -#define DEFAULT_BUCKETS 4096 - -#if 0 -#define INFO_MSG(fmt...) do { \ - info_msg(fmt); \ -} while (0) -#else -#define INFO_MSG(fmt...) -#endif - -struct hashentry { - char* key; /* key '0' term. str */ - char* value; /* payload '0' term. str */ - - hashentry_t next; -}; - -struct hashmap { - size_t entries; /* current #entries */ - size_t maxsize; /* no. of hash buckets */ - hashentry_t* data; /* array of buckets */ -}; - -static int -is_empty(hashentry_t l) -{ - return l == NULL ? 1 : 0; -} - -hashmap_t -hashmap_new(void) -{ - hashmap_t res; - res = (hashmap_t) calloc(1, sizeof(struct hashmap)); - - if (res == NULL) - return NULL; - - res->maxsize = DEFAULT_BUCKETS; - res->entries = 0; - - res->data = (hashentry_t*) - calloc(1, res->maxsize * sizeof(struct hashentry)); - - if (res->data == NULL) - return NULL; - - return res; -} - -static hashentry_t -new_entry(const char* key, const char* value) -{ - hashentry_t res; - - res = (hashentry_t) calloc(1, sizeof(struct hashentry)); - - if (res == NULL) - return NULL; - - /* allocate key and value and copy them */ - res->key = strdup(key); - if (res->key == NULL) { - free(res); - return NULL; - } - - res->value = strdup(value); - if (res->value == NULL) { - free(res->key); - free(res); - return NULL; - } - - res->next = NULL; - - return res; -} - -static hashentry_t -free_entry(hashentry_t e) -{ - if (!is_empty(e)) { - if(e->key != NULL) { - free(e->key); - } - if(e->value != NULL) - free(e->value); - free(e); - } - - return NULL; -} - -static hashentry_t -remove_entry(hashentry_t l, const char* key, size_t* entries) -{ - hashentry_t lnext; - if (is_empty(l)) - return NULL; - - if(strcmp(l->key,key) == 0) { - lnext = l->next; - l = free_entry(l); - (*entries)--; - return lnext; - } - - l->next = remove_entry(l->next, key, entries); - - return l; -} - -static hashentry_t -insert_entry(hashentry_t l, hashentry_t e, size_t* entries) -{ - if (is_empty(l)) { - (*entries)++; - return e; - } - - /* check for update */ - if (strcmp(l->key, e->key) == 0) { - e->next = l->next; - l = free_entry(l); - return e; - } - - l->next = insert_entry(l->next, e, entries); - return l; -} - -static hashentry_t -remove_all(hashentry_t l, size_t* entries) -{ - hashentry_t lnext; - if (is_empty(l)) - return NULL; - - lnext = l->next; - free_entry(l); - (*entries)--; - - return remove_all(lnext, entries); -} - -static const char* -value_lookup(hashentry_t l, const char* key) -{ - if (is_empty(l)) - return NULL; - - if (strcmp(l->key, key) == 0) - return l->value; - - return value_lookup(l->next, key); -} - -static void -print_all(hashentry_t l) -{ - if (is_empty(l)) { - printf("\n"); - return; - } - - printf("%s=%s", l->key, l->value); - if (!is_empty(l->next)) { - printf(","); - } - - print_all(l->next); -} - -static void -keys_to_array(hashentry_t l, const char** a, size_t* i) -{ - if (is_empty(l)) - return; - - a[*i] = l->key; - (*i)++; - - keys_to_array(l->next, a, i); -} - -uint32_t -hash_str(const char* str, uint32_t mapsize) -{ - uint32_t hash = 0; - uint32_t x = 0; - uint32_t i = 0; - size_t len = strlen(str); - - for(i = 0; i < len; str++, i++) { - hash = (hash << 4) + (*str); - if((x = hash & 0xF0000000L) != 0) { - hash ^= (x >> 24); - hash &= ~x; - } - } - - return (hash & 0x7FFFFFFF) % mapsize; -} - - -int -hashmap_is_empty(hashmap_t map) -{ - if (map == NULL) - return -EINVAL; - - return map->entries > 0 ? 1 : 0; -} - -const char* -hashmap_lookup(hashmap_t map, const char* key) -{ - uint32_t i; - - if ((map == NULL) || (key == NULL)) - return NULL; - - i = hash_str(key, map->maxsize); - - return value_lookup(map->data[i], key); -} - -int -hashmap_add(hashmap_t map, const char* key, const char* value) -{ - uint32_t i; - hashentry_t entry; - - if ((map == NULL) || (key == NULL) || (value == NULL)) - return -EINVAL; - - i = hash_str(key, map->maxsize); - entry = new_entry(key, value); - if (entry == NULL) - return -ENOMEM; - - map->data[i] = insert_entry(map->data[i], - entry, &map->entries); - - INFO_MSG("HASH_ADD: chain[%d] key:%s val:%s",i, key, value); - return 0; -} - -int -hashmap_remove(hashmap_t map, const char* key) -{ - uint32_t i; - - if ((map == NULL) || (key == NULL)) - return -EINVAL; - - i = hash_str(key, map->maxsize); - map->data[i] = remove_entry(map->data[i], key, &map->entries); - - return 0; -} - -size_t -hashmap_size(hashmap_t map) -{ - if (map != NULL) - return map->entries; - else - return 0; -} - -int -hashmap_free(hashmap_t map) -{ - size_t i; - - if (map == NULL) - return -EINVAL; - - /* "children" first */ - for(i = 0; i < map->maxsize; i++) { - map->data[i] = remove_all(map->data[i], &map->entries); - } - free(map->data); - free(map); - - return 0; -} - -int -hashmap_dump(hashmap_t map) -{ - size_t i; - if (map == NULL) - return -EINVAL; - - for(i = 0; i < map->maxsize; i++) { - if (map->data[i] != NULL) { - printf("[%zd]: ", i); - print_all(map->data[i]); - } - } - - return 0; -} - -static const char** -sort_key_vector(const char** a, size_t size) -{ - /* uses bubblesort */ - size_t i, j; - const char* tmp; - - if (size <= 0) - return a; - - for (i = size - 1; i > 0; i--) { - for (j = 0; j < i; j++) { - if (strcmp(a[j], a[j+1]) > 0) { - tmp = a[j]; - a[j] = a[j+1]; - a[j+1] = tmp; - } - } - } - return a; -} - -const char** -hashmap_get_key_vector(hashmap_t map, size_t* size, int sort) -{ - const char** res; - size_t i, j; - *size = map->entries; - - res = (const char**) malloc(*size * sizeof(char*)); - if (res == NULL) - return NULL; - - j = 0; - for(i=0; i < map->maxsize; i++) { - keys_to_array(map->data[i], res, &j); - } - - if (sort) - res = sort_key_vector(res, *size); - - return res; -} - -int -hashmap_key_is_in_vector(const char** vec, size_t size, const char* key) -{ - size_t i; - for (i = 0; i < size; i++) { - if (strcmp(vec[i], key) == 0) /* found */ - return 1; - } - - return 0; -} - -const char** -hashmap_get_update_key_vector(const char** vec1, size_t vec1_size, - const char** vec2, size_t vec2_size, size_t* res_size) -{ - const char** res; - size_t i, j; - - *res_size = vec2_size; - - res = (const char**) malloc(*res_size * sizeof(char*)); - if (res == NULL) - return NULL; - - /* get all keys from vec2 which are not set in vec1 */ - j = 0; - for (i = 0; i < vec2_size; i++) { - if (!hashmap_key_is_in_vector(vec1, vec1_size, vec2[i])) - res[j++] = vec2[i]; - } - - *res_size = j; - return res; -} diff --git a/ubi-utils/src/hashmap.h b/ubi-utils/src/hashmap.h deleted file mode 100644 index 1b13e95..0000000 --- a/ubi-utils/src/hashmap.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __HASHMAP_H__ -#define __HASHMAP_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -#include <stdlib.h> -#include <stdint.h> - -typedef struct hashentry *hashentry_t; -typedef struct hashmap *hashmap_t; - -hashmap_t hashmap_new(void); -int hashmap_free(hashmap_t map); - -int hashmap_add(hashmap_t map, const char* key, const char* value); -int hashmap_update(hashmap_t map, const char* key, const char* value); -int hashmap_remove(hashmap_t map, const char* key); -const char* hashmap_lookup(hashmap_t map, const char* key); - -const char** hashmap_get_key_vector(hashmap_t map, size_t* size, int sort); -int hashmap_key_is_in_vector(const char** vec, size_t size, const char* key); -const char** hashmap_get_update_key_vector(const char** vec1, size_t vec1_size, - const char** vec2, size_t vec2_size, size_t* res_size); - -int hashmap_dump(hashmap_t map); - -int hashmap_is_empty(hashmap_t map); -size_t hashmap_size(hashmap_t map); - -uint32_t hash_str(const char* str, uint32_t mapsize); - -#endif /* __HASHMAP_H__ */ diff --git a/ubi-utils/src/libiniparser.c b/ubi-utils/src/libiniparser.c new file mode 100644 index 0000000..3bea51e --- /dev/null +++ b/ubi-utils/src/libiniparser.c @@ -0,0 +1,646 @@ + +/*-------------------------------------------------------------------------*/ +/** + @file iniparser.c + @author N. Devillard + @date Sep 2007 + @version 3.0 + @brief Parser for ini files. +*/ +/*--------------------------------------------------------------------------*/ +/* + $Id: iniparser.c,v 2.18 2008-01-03 18:35:39 ndevilla Exp $ + $Revision: 2.18 $ + $Date: 2008-01-03 18:35:39 $ +*/ +/*---------------------------- Includes ------------------------------------*/ +#include <ctype.h> +#include <libiniparser.h> + +/*---------------------------- Defines -------------------------------------*/ +#define ASCIILINESZ (1024) +#define INI_INVALID_KEY ((char*)-1) + +/*--------------------------------------------------------------------------- + Private to this module + ---------------------------------------------------------------------------*/ +/** + * This enum stores the status for each parsed line (internal use only). + */ +typedef enum _line_status_ { + LINE_UNPROCESSED, + LINE_ERROR, + LINE_EMPTY, + LINE_COMMENT, + LINE_SECTION, + LINE_VALUE +} line_status ; + +/*-------------------------------------------------------------------------*/ +/** + @brief Convert a string to lowercase. + @param s String to convert. + @return ptr to statically allocated string. + + This function returns a pointer to a statically allocated string + containing a lowercased version of the input string. Do not free + or modify the returned string! Since the returned string is statically + allocated, it will be modified at each function call (not re-entrant). + */ +/*--------------------------------------------------------------------------*/ +static char * strlwc(const char * s) +{ + static char l[ASCIILINESZ+1]; + int i ; + + if (s==NULL) return NULL ; + memset(l, 0, ASCIILINESZ+1); + i=0 ; + while (s[i] && i<ASCIILINESZ) { + l[i] = (char)tolower((int)s[i]); + i++ ; + } + l[ASCIILINESZ]=(char)0; + return l ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Remove blanks at the beginning and the end of a string. + @param s String to parse. + @return ptr to statically allocated string. + + This function returns a pointer to a statically allocated string, + which is identical to the input string, except that all blank + characters at the end and the beg. of the string have been removed. + Do not free or modify the returned string! Since the returned string + is statically allocated, it will be modified at each function call + (not re-entrant). + */ +/*--------------------------------------------------------------------------*/ +static char * strstrip(char * s) +{ + static char l[ASCIILINESZ+1]; + char * last ; + + if (s==NULL) return NULL ; + + while (isspace((int)*s) && *s) s++; + memset(l, 0, ASCIILINESZ+1); + strcpy(l, s); + last = l + strlen(l); + while (last > l) { + if (!isspace((int)*(last-1))) + break ; + last -- ; + } + *last = (char)0; + return (char*)l ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get number of sections in a dictionary + @param d Dictionary to examine + @return int Number of sections found in dictionary + + This function returns the number of sections found in a dictionary. + The test to recognize sections is done on the string stored in the + dictionary: a section name is given as "section" whereas a key is + stored as "section:key", thus the test looks for entries that do not + contain a colon. + + This clearly fails in the case a section name contains a colon, but + this should simply be avoided. + + This function returns -1 in case of error. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getnsec(dictionary * d) +{ + int i ; + int nsec ; + + if (d==NULL) return -1 ; + nsec=0 ; + for (i=0 ; i<d->size ; i++) { + if (d->key[i]==NULL) + continue ; + if (strchr(d->key[i], ':')==NULL) { + nsec ++ ; + } + } + return nsec ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get name for section n in a dictionary. + @param d Dictionary to examine + @param n Section number (from 0 to nsec-1). + @return Pointer to char string + + This function locates the n-th section in a dictionary and returns + its name as a pointer to a string statically allocated inside the + dictionary. Do not free or modify the returned string! + + This function returns NULL in case of error. + */ +/*--------------------------------------------------------------------------*/ +char * iniparser_getsecname(dictionary * d, int n) +{ + int i ; + int foundsec ; + + if (d==NULL || n<0) return NULL ; + foundsec=0 ; + for (i=0 ; i<d->size ; i++) { + if (d->key[i]==NULL) + continue ; + if (strchr(d->key[i], ':')==NULL) { + foundsec++ ; + if (foundsec>n) + break ; + } + } + if (foundsec<=n) { + return NULL ; + } + return d->key[i] ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump. + @param f Opened file pointer to dump to. + @return void + + This function prints out the contents of a dictionary, one element by + line, onto the provided file pointer. It is OK to specify @c stderr + or @c stdout as output files. This function is meant for debugging + purposes mostly. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_dump(dictionary * d, FILE * f) +{ + int i ; + + if (d==NULL || f==NULL) return ; + for (i=0 ; i<d->size ; i++) { + if (d->key[i]==NULL) + continue ; + if (d->val[i]!=NULL) { + fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); + } else { + fprintf(f, "[%s]=UNDEF\n", d->key[i]); + } + } + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Save a dictionary to a loadable ini file + @param d Dictionary to dump + @param f Opened file pointer to dump to + @return void + + This function dumps a given dictionary into a loadable ini file. + It is Ok to specify @c stderr or @c stdout as output files. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_dump_ini(dictionary * d, FILE * f) +{ + int i, j ; + char keym[ASCIILINESZ+1]; + int nsec ; + char * secname ; + int seclen ; + + if (d==NULL || f==NULL) return ; + + nsec = iniparser_getnsec(d); + if (nsec<1) { + /* No section in file: dump all keys as they are */ + for (i=0 ; i<d->size ; i++) { + if (d->key[i]==NULL) + continue ; + fprintf(f, "%s = %s\n", d->key[i], d->val[i]); + } + return ; + } + for (i=0 ; i<nsec ; i++) { + secname = iniparser_getsecname(d, i) ; + seclen = (int)strlen(secname); + fprintf(f, "\n[%s]\n", secname); + sprintf(keym, "%s:", secname); + for (j=0 ; j<d->size ; j++) { + if (d->key[j]==NULL) + continue ; + if (!strncmp(d->key[j], keym, seclen+1)) { + fprintf(f, + "%-30s = %s\n", + d->key[j]+seclen+1, + d->val[j] ? d->val[j] : ""); + } + } + } + fprintf(f, "\n"); + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key + @param d Dictionary to search + @param key Key string to look for + @param def Default value to return if key not found. + @return pointer to statically allocated character string + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the pointer passed as 'def' is returned. + The returned char pointer is pointing to a string allocated in + the dictionary, do not free or modify it. + */ +/*--------------------------------------------------------------------------*/ +char * iniparser_getstring(dictionary * d, const char * key, char * def) +{ + char * lc_key ; + char * sval ; + + if (d==NULL || key==NULL) + return def ; + + lc_key = strlwc(key); + sval = dictionary_get(d, lc_key, def); + return sval ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to an int + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + Supported values for integers include the usual C notation + so decimal, octal (starting with 0) and hexadecimal (starting with 0x) + are supported. Examples: + + "42" -> 42 + "042" -> 34 (octal -> decimal) + "0x42" -> 66 (hexa -> decimal) + + Warning: the conversion may overflow in various ways. Conversion is + totally outsourced to strtol(), see the associated man page for overflow + handling. + + Credits: Thanks to A. Becker for suggesting strtol() + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getint(dictionary * d, const char * key, int notfound) +{ + char * str ; + + str = iniparser_getstring(d, key, INI_INVALID_KEY); + if (str==INI_INVALID_KEY) return notfound ; + return (int)strtol(str, NULL, 0); +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a double + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return double + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + */ +/*--------------------------------------------------------------------------*/ +double iniparser_getdouble(dictionary * d, char * key, double notfound) +{ + char * str ; + + str = iniparser_getstring(d, key, INI_INVALID_KEY); + if (str==INI_INVALID_KEY) return notfound ; + return atof(str); +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a boolean + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + A true boolean is found if one of the following is matched: + + - A string starting with 'y' + - A string starting with 'Y' + - A string starting with 't' + - A string starting with 'T' + - A string starting with '1' + + A false boolean is found if one of the following is matched: + + - A string starting with 'n' + - A string starting with 'N' + - A string starting with 'f' + - A string starting with 'F' + - A string starting with '0' + + The notfound value returned if no boolean is identified, does not + necessarily have to be 0 or 1. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getboolean(dictionary * d, const char * key, int notfound) +{ + char * c ; + int ret ; + + c = iniparser_getstring(d, key, INI_INVALID_KEY); + if (c==INI_INVALID_KEY) return notfound ; + if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { + ret = 1 ; + } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { + ret = 0 ; + } else { + ret = notfound ; + } + return ret; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Finds out if a given entry exists in a dictionary + @param ini Dictionary to search + @param entry Name of the entry to look for + @return integer 1 if entry exists, 0 otherwise + + Finds out if a given entry exists in the dictionary. Since sections + are stored as keys with NULL associated values, this is the only way + of querying for the presence of sections in a dictionary. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_find_entry( + dictionary * ini, + char * entry +) +{ + int found=0 ; + if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { + found = 1 ; + } + return found ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Set an entry in a dictionary. + @param ini Dictionary to modify. + @param entry Entry to modify (entry name) + @param val New value to associate to the entry. + @return int 0 if Ok, -1 otherwise. + + If the given entry can be found in the dictionary, it is modified to + contain the provided value. If it cannot be found, -1 is returned. + It is Ok to set val to NULL. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_set(dictionary * ini, char * entry, char * val) +{ + return dictionary_set(ini, strlwc(entry), val) ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete an entry in a dictionary + @param ini Dictionary to modify + @param entry Entry to delete (entry name) + @return void + + If the given entry can be found, it is deleted from the dictionary. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_unset(dictionary * ini, char * entry) +{ + dictionary_unset(ini, strlwc(entry)); +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Load a single line from an INI file + @param input_line Input line, may be concatenated multi-line input + @param section Output space to store section + @param key Output space to store key + @param value Output space to store value + @return line_status value + */ +/*--------------------------------------------------------------------------*/ +static line_status iniparser_line( + char * input_line, + char * section, + char * key, + char * value) +{ + line_status sta ; + char line[ASCIILINESZ+1]; + int len ; + + strcpy(line, strstrip(input_line)); + len = (int)strlen(line); + + sta = LINE_UNPROCESSED ; + if (len<1) { + /* Empty line */ + sta = LINE_EMPTY ; + } else if (line[0]=='#') { + /* Comment line */ + sta = LINE_COMMENT ; + } else if (line[0]=='[' && line[len-1]==']') { + /* Section name */ + sscanf(line, "[%[^]]", section); + strcpy(section, strstrip(section)); + strcpy(section, strlwc(section)); + sta = LINE_SECTION ; + } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 + || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2 + || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { + /* Usual key=value, with or without comments */ + strcpy(key, strstrip(key)); + strcpy(key, strlwc(key)); + strcpy(value, strstrip(value)); + /* + * sscanf cannot handle '' or "" as empty values + * this is done here + */ + if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) { + value[0]=0 ; + } + sta = LINE_VALUE ; + } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 + || sscanf(line, "%[^=] %[=]", key, value) == 2) { + /* + * Special cases: + * key= + * key=; + * key=# + */ + strcpy(key, strstrip(key)); + strcpy(key, strlwc(key)); + value[0]=0 ; + sta = LINE_VALUE ; + } else { + /* Generate syntax error */ + sta = LINE_ERROR ; + } + return sta ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Parse an ini file and return an allocated dictionary object + @param ininame Name of the ini file to read. + @return Pointer to newly allocated dictionary + + This is the parser for ini files. This function is called, providing + the name of the file to be read. It returns a dictionary object that + should not be accessed directly, but through accessor functions + instead. + + The returned dictionary must be freed using iniparser_freedict(). + */ +/*--------------------------------------------------------------------------*/ +dictionary * iniparser_load(const char * ininame) +{ + FILE * in ; + + char line [ASCIILINESZ+1] ; + char section [ASCIILINESZ+1] ; + char key [ASCIILINESZ+1] ; + char tmp [ASCIILINESZ+1] ; + char val [ASCIILINESZ+1] ; + + int last=0 ; + int len ; + int lineno=0 ; + int errs=0; + + dictionary * dict ; + + if ((in=fopen(ininame, "r"))==NULL) { + fprintf(stderr, "iniparser: cannot open %s\n", ininame); + return NULL ; + } + + dict = dictionary_new(0) ; + if (!dict) { + fclose(in); + return NULL ; + } + + memset(line, 0, ASCIILINESZ); + memset(section, 0, ASCIILINESZ); + memset(key, 0, ASCIILINESZ); + memset(val, 0, ASCIILINESZ); + last=0 ; + + while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { + lineno++ ; + len = (int)strlen(line)-1; + /* Safety check against buffer overflows */ + if (line[len]!='\n') { + fprintf(stderr, + "iniparser: input line too long in %s (%d)\n", + ininame, + lineno); + dictionary_del(dict); + fclose(in); + return NULL ; + } + /* Get rid of \n and spaces at end of line */ + while ((len>=0) && + ((line[len]=='\n') || (isspace(line[len])))) { + line[len]=0 ; + len-- ; + } + /* Detect multi-line */ + if (line[len]=='\\') { + /* Multi-line value */ + last=len ; + continue ; + } else { + last=0 ; + } + switch (iniparser_line(line, section, key, val)) { + case LINE_EMPTY: + case LINE_COMMENT: + break ; + + case LINE_SECTION: + errs = dictionary_set(dict, section, NULL); + break ; + + case LINE_VALUE: + sprintf(tmp, "%s:%s", section, key); + errs = dictionary_set(dict, tmp, val) ; + break ; + + case LINE_ERROR: + fprintf(stderr, "iniparser: syntax error in %s (%d):\n", + ininame, + lineno); + fprintf(stderr, "-> %s\n", line); + errs++ ; + break; + + default: + break ; + } + memset(line, 0, ASCIILINESZ); + last=0; + if (errs<0) { + fprintf(stderr, "iniparser: memory allocation failure\n"); + break ; + } + } + if (errs) { + dictionary_del(dict); + dict = NULL ; + } + fclose(in); + return dict ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Free all memory associated to an ini dictionary + @param d Dictionary to free + @return void + + Free all memory associated to an ini dictionary. + It is mandatory to call this function before the dictionary object + gets out of the current context. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_freedict(dictionary * d) +{ + dictionary_del(d); +} + +/* vim: set ts=4 et sw=4 tw=75 */ diff --git a/ubi-utils/src/libpfi.c b/ubi-utils/src/libpfi.c deleted file mode 100644 index 6de24ea..0000000 --- a/ubi-utils/src/libpfi.c +++ /dev/null @@ -1,628 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * Copyright (C) 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * 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 c3a0f9c..9cbd1b7 100644 --- a/ubi-utils/src/libubigen.c +++ b/ubi-utils/src/libubigen.c @@ -38,35 +38,6 @@ #define PROGRAM_NAME "libubigen" /** - * 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) -{ - struct ubi_vtbl_record *vtbl; - int i; - - if (*size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE) - *size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE; - - vtbl = calloc(1, *size); - if (!vtbl) - return NULL; - - for (i = 0; i < UBI_MAX_VOLUMES; i++) { - uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i], - UBI_VTBL_RECORD_SIZE_CRC); - vtbl[i].crc = __cpu_to_be32(crc); - } - - return vtbl; -} - -/** * ubigen_info_init - initialize libubigen. * @ui: libubigen information * @peb_size: flash physical eraseblock size @@ -93,28 +64,67 @@ void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size, ui->leb_size = peb_size - ui->data_offs; ui->ubi_ver = ubi_ver; ui->ec = ec; + + ui->vtbl_size = ui->leb_size; + if (ui->vtbl_size > UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE) + ui->vtbl_size = UBI_MAX_VOLUMES * UBI_VTBL_RECORD_SIZE; + ui->max_volumes = ui->vtbl_size / UBI_VTBL_RECORD_SIZE; +} + +/** + * ubigen_create_empty_vtbl - creates empty volume table. + * + * This function creates an empty volume table and returns a pointer to it in + * case of success and %NULL in case of failure. The returned object has to be + * freed with 'free()' call. + */ +struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui) +{ + struct ubi_vtbl_record *vtbl; + int i; + + vtbl = calloc(1, ui->vtbl_size); + if (!vtbl) { + errmsg("cannot allocate %d bytes of memory", ui->vtbl_size); + return NULL; + } + + for (i = 0; i < UBI_MAX_VOLUMES; i++) { + uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i], + UBI_VTBL_RECORD_SIZE_CRC); + vtbl[i].crc = __cpu_to_be32(crc); + } + + return vtbl; } /** * ubigen_add_volume - add a volume to the volume table. - * @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 + * @vi: volume 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, +int ubigen_add_volume(const struct ubigen_info *ui, const struct ubigen_vol_info *vi, struct ubi_vtbl_record *vtbl) { struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id]; uint32_t tmp; + if (vi->id >= ui->max_volumes) { + errmsg("too high volume id %d, max. volumes is %d", + vi->id, ui->max_volumes); + return -1; + } + if (vi->alignment >= ui->leb_size) { + errmsg("too large alignment %d, max is %d (LEB size)", + vi->alignment, ui->leb_size); + return -1; + } + 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); @@ -129,6 +139,7 @@ void ubigen_add_volume(const struct ubigen_info *ui, tmp = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC); vtbl_rec->crc = __cpu_to_be32(tmp); + return 0; } /** @@ -213,6 +224,17 @@ int ubigen_write_volume(const struct ubigen_info *ui, int len = vi->usable_leb_size, rd, lnum = 0; char inbuf[ui->leb_size], outbuf[ui->peb_size]; + if (vi->id >= ui->max_volumes) { + errmsg("too high volume id %d, max. volumes is %d", + vi->id, ui->max_volumes); + return -1; + } + if (vi->alignment >= ui->leb_size) { + errmsg("too large alignment %d, max is %d (LEB size)", + vi->alignment, ui->leb_size); + return -1; + } + memset(outbuf, 0xFF, ui->data_offs); init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf); diff --git a/ubi-utils/src/list.c b/ubi-utils/src/list.c deleted file mode 100644 index a701158..0000000 --- a/ubi-utils/src/list.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Oliver Lohmann - */ - -#include <stdlib.h> -#include <assert.h> -#include <stdio.h> - -#include "list.h" - -int -is_empty(struct list_entry *l) -{ - return l == NULL; -} - -info_t -head(struct list_entry *l) -{ - assert(!is_empty(l)); - return l->info; -} - -struct list_entry * -tail(struct list_entry *l) -{ - assert(!is_empty(l)); - return l->next; -} - -struct list_entry * -remove_head(struct list_entry *l) -{ - struct list_entry *res; - assert(!is_empty(l)); - - res = l->next; - free(l); - return res; -} - -struct list_entry * -cons(info_t e, struct list_entry *l) -{ - struct list_entry *res = malloc(sizeof(*l)); - if (!res) - return NULL; - res->info = e; - res->next = l; - - return res; -} - -struct list_entry * -prepend_elem(info_t e, struct list_entry *l) -{ - return cons(e,l); -} - -struct list_entry * -append_elem(info_t e, struct list_entry *l) -{ - if (is_empty(l)) { - return cons(e,l); - } - l->next = append_elem(e, l->next); - - return 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); - - switch (cmp(e, l->info)) { - case -1: - case 0: - return l; - break; - case 1: - l->next = insert_sorted(cmp, e, l); - break; - default: - break; - } - - /* never reached */ - return NULL; -} - -struct list_entry * -remove_all(free_func_t free_func, struct list_entry *l) -{ - if (is_empty(l)) - return l; - struct list_entry *lnext = l->next; - - if (free_func && l->info) { - free_func(&(l->info)); - } - free(l); - - return remove_all(free_func, lnext); -} - - -info_t -is_in(cmp_func_t cmp, info_t e, struct list_entry *l) -{ - return - (is_empty(l)) - ? NULL - : (cmp(e, l->info)) == 0 ? l->info : is_in(cmp, e, l->next); -} - - -void -apply(process_func_t process_func, struct list_entry *l) -{ - struct list_entry *ptr; - void *i; - list_for_each(i, ptr, l) { - process_func(i); - } -} diff --git a/ubi-utils/src/list.h b/ubi-utils/src/list.h deleted file mode 100644 index 58bfe7e..0000000 --- a/ubi-utils/src/list.h +++ /dev/null @@ -1,61 +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 - */ - -#ifndef __UBIUTILS_LIST_H__ -#define __UBIUTILS_LIST_H__ - -#include <stdint.h> - -#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 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 list_entry { - struct list_entry *next; - info_t info; -}; - -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/pfi2bin.c b/ubi-utils/src/pfi2bin.c deleted file mode 100644 index 4289fca..0000000 --- a/ubi-utils/src/pfi2bin.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * Copyright (C) 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * - * Convert a PFI file (partial flash image) into a plain binary file. - * This tool can be used to prepare the data to be burned into flash - * chips in a manufacturing step where the flashes are written before - * being soldered onto the hardware. For NAND images one more step may be - * needed to add the right OOB data to the binary image. - * - * Authors: Oliver Lohmann - * Artem Bityutskiy - */ - -#include <stdlib.h> -#include <getopt.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -#include <mtd/ubi-header.h> -#include <libubigen.h> -#include <libpfi.h> -#include "common.h" -#include "list.h" - -#define PROGRAM_VERSION "1.5" -#define PROGRAM_NAME "pfi2bin" - -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" -"use default values."; - -static const char *optionsstr = -"-o, --output=<file name> output file name (default is stdout)\n" -"-p, --peb-size=<bytes> size of the physical eraseblock of the flash this\n" -" UBI image is created for in bytes, kilobytes (KiB),\n" -" or megabytes (MiB) (mandatory parameter)\n" -"-m, --min-io-size=<bytes> minimum input/output unit size of the flash in bytes\n" -"-s, --sub-page-size=<bytes> minimum input/output unit used for UBI headers, e.g.\n" -" sub-page size in case of NAND flash (equivalent to\n" -" the minimum input/output unit size by default)\n" -"-O, --vid-hdr-offset=<num> offset if the VID header from start of the physical\n" -" eraseblock (default is the second minimum I/O unit\n" -" or sub-page, if it was specified)\n" -"-e, --erase-counter=<num> the erase counter value to put to EC headers\n" -" (default is 0)\n" -"-x, --ubi-ver=<num> UBI version number to put to EC headers\n" -" (default is 1)\n" -"-h, --help print help message\n" -"-V, --version print program version"; - -static const char *usage = -"Usage: " PROGRAM_NAME "[-o filename] [-h] [-V] [--output=<filename>] [--help] [--version] pfifile\n" -"Example:" PROGRAM_NAME "-o fs.raw fs.pfi"; - -struct option long_options[] = { - { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, - { .name = "peb-size", .has_arg = 1, .flag = NULL, .val = 'p' }, - { .name = "min-io-size", .has_arg = 1, .flag = NULL, .val = 'm' }, - { .name = "sub-page-size", .has_arg = 1, .flag = NULL, .val = 's' }, - { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' }, - { .name = "erase-counter", .has_arg = 1, .flag = NULL, .val = 'e' }, - { .name = "ubi-ver", .has_arg = 1, .flag = NULL, .val = 'x' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0} -}; - -struct args { - const char *f_in; - const char *f_out; - FILE *fp_in; - FILE *fp_out; - int peb_size; - int min_io_size; - int subpage_size; - int vid_hdr_offs; - int ec; - int ubi_ver; -}; - -static struct args args = { - .f_out = NULL, - .peb_size = -1, - .min_io_size = -1, - .subpage_size = -1, - .vid_hdr_offs = 0, - .ec = 0, - .ubi_ver = 1, -}; - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key; - char *endp; - - key = getopt_long(argc, argv, "o:p:m:s:O:e:x:hV", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'o': - args.fp_out = fopen(optarg, "wb"); - if (!args.fp_out) { - errmsg("cannot open file \"%s\"", optarg); - return -1; - } - args.f_out = optarg; - break; - - case 'p': - args.peb_size = strtoull(optarg, &endp, 0); - if (endp == optarg || args.peb_size <= 0) { - errmsg("bad physical eraseblock size: \"%s\"", optarg); - return -1; - } - if (*endp != '\0') { - int mult = ubiutils_get_multiplier(endp); - - if (mult == -1) { - errmsg("bad size specifier: \"%s\" - " - "should be 'KiB', 'MiB' or 'GiB'", endp); - return -1; - } - args.peb_size *= mult; - } - break; - - case 'm': - args.min_io_size = strtoull(optarg, &endp, 0); - if (endp == optarg || args.min_io_size <= 0) { - errmsg("bad min. I/O unit size: \"%s\"", optarg); - return -1; - } - if (*endp != '\0') { - int mult = ubiutils_get_multiplier(endp); - - if (mult == -1) { - errmsg("bad size specifier: \"%s\" - " - "should be 'KiB', 'MiB' or 'GiB'", endp); - return -1; - } - args.min_io_size *= mult; - } - break; - - case 's': - args.subpage_size = strtoull(optarg, &endp, 0); - if (endp == optarg || args.subpage_size <= 0) { - errmsg("bad sub-page size: \"%s\"", optarg); - return -1; - } - if (*endp != '\0') { - int mult = ubiutils_get_multiplier(endp); - - if (mult == -1) { - errmsg("bad size specifier: \"%s\" - " - "should be 'KiB', 'MiB' or 'GiB'", endp); - return -1; - } - args.subpage_size *= mult; - } - break; - - case 'O': - args.vid_hdr_offs = strtoul(optarg, &endp, 0); - if (endp == optarg || args.vid_hdr_offs < 0) { - errmsg("bad VID header offset: \"%s\"", optarg); - return -1; - } - break; - - case 'e': - args.ec = strtoul(optarg, &endp, 0); - if (endp == optarg || args.ec < 0) { - errmsg("bad erase counter value: \"%s\"", optarg); - return -1; - } - break; - - case 'x': - args.ubi_ver = strtoul(optarg, &endp, 0); - if (endp == optarg || args.ubi_ver < 0) { - errmsg("bad UBI version: \"%s\"", optarg); - return -1; - } - break; - - case 'h': - fprintf(stderr, "%s\n\n", doc); - fprintf(stderr, "%s\n\n", usage); - fprintf(stderr, "%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (optind == argc) { - errmsg("input PFI file was not specified (use -h for help)"); - return -1; - } - - if (optind != argc - 1) { - errmsg("more then one input PFI file was specified (use -h for help)"); - return -1; - } - - if (args.peb_size < 0) { - errmsg("physical eraseblock size was not specified (use -h for help)"); - return -1; - } - - if (args.min_io_size < 0) { - errmsg("min. I/O unit size was not specified (use -h for help)"); - return -1; - } - - if (args.subpage_size < 0) - args.subpage_size = args.min_io_size; - - args.f_in = argv[optind++]; - args.fp_in = fopen(args.f_in, "rb"); - if (!args.fp_in) { - errmsg("cannot open file \"%s\"", args.f_in); - return -1; - } - - if (!args.f_out) { - args.f_out = "stdout"; - args.fp_out = stdout; - } - - return 0; -} - -/** - * 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 void pfi2vol_info(const struct pfi_ubi *pfi, int n, - struct ubigen_vol_info *vi, - const struct ubigen_info *ui) -{ - 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; - } - - vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size; - vi->compat = 0; -} - -static int create_flash_image(void) -{ - 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; - } - - ubigen_info_init(&ui, args.peb_size, args.min_io_size, - args.subpage_size, args.vid_hdr_offs, args.ubi_ver, - args.ec); - - err = read_pfi_headers(&ubi_list, args.fp_in); - if (err != 0) { - errmsg("cannot read PFI headers, error %d", err); - goto error; - } - - /* 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; - - pfi2vol_info(pfi, i, &vi, &ui); - ubigen_add_volume(&ui, &vi, vtbl); - } - - err = ubigen_write_layout_vol(&ui, vtbl, args.fp_out); - if (err) { - errmsg("cannot create layout volume"); - goto error; - } - - /* 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; - } - - 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; - } - } - - if (args.fp_out != stdout) { - i = ftell(args.fp_out); - if (i == -1) { - errmsg("cannot seek output file"); - perror("ftell"); - goto error; - } - - printf("physical eraseblocks written: %d (", i / ui.peb_size); - ubiutils_print_bytes(i, 0); - printf(")\n"); - } - -error: - free(vtbl); - ubi_list = remove_all((free_func_t)&free_pfi_ubi, ubi_list); - return err; -} - -int main(int argc, char * const argv[]) -{ - int err; - - err = parse_opt(argc, argv); - if (err) - return -1; - - err = create_flash_image(); - if (err) - remove(args.f_out); - - return err; -} diff --git a/ubi-utils/src/pfiflash.h b/ubi-utils/src/pfiflash.h deleted file mode 100644 index 039705d..0000000 --- a/ubi-utils/src/pfiflash.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef __PFIFLASH_H__ -#define __PFIFLASH_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * - * @file pfi.h - * - * @author Oliver Lohmann <oliloh@de.ibm.com> - * - * @brief The pfiflash library offers an interface for using the - * pfiflash * utility. - */ - -#include <stdio.h> /* FILE */ - -#define PFIFLASH_MAX_ERR_BUF_SIZE 1024 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum pdd_handling_t -{ - PDD_KEEP = 0, - PDD_MERGE, - PDD_OVERWRITE, - PDD_HANDLING_NUM, /* always the last item */ -} pdd_handling_t; /**< Possible PDD handle algorithms. */ - -/** - * @brief Flashes a PFI file to UBI Device 0. - * @param complete [0|1] Do a complete system update. - * @param seqnum Index in a redundant group. - * @param compare [0|1] Compare contents. - * @param pdd_handling The PDD handling algorithm. - * @param rawdev Device to use for raw flashing - * @param err_buf An error buffer. - * @param err_buf_size Size of the error buffer. - */ -int pfiflash_with_options(FILE* pfi, int complete, int seqnum, int compare, - pdd_handling_t pdd_handling, const char* rawdev, - char *err_buf, size_t err_buf_size); - -/** - * @brief Flashes a PFI file to UBI Device 0. - * @param complete [0|1] Do a complete system update. - * @param seqnum Index in a redundant group. - * @param pdd_handling The PDD handling algorithm. - * @param err_buf An error buffer. - * @param err_buf_size Size of the error buffer. - */ -int pfiflash(FILE* pfi, int complete, int seqnum, pdd_handling_t pdd_handling, - char *err_buf, size_t err_buf_size); - -#ifdef __cplusplus -} -#endif - -#endif /* __PFIFLASH_H__ */ diff --git a/ubi-utils/src/ubinize.c b/ubi-utils/src/ubinize.c new file mode 100644 index 0000000..28991f9 --- /dev/null +++ b/ubi-utils/src/ubinize.c @@ -0,0 +1,615 @@ +/* + * Copyright (C) 2008 Nokia Corporation + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Generate UBI images. + * + * Authors: Artem Bityutskiy + * Oliver Lohmann + */ + +#include <stdlib.h> +#include <getopt.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <mtd/ubi-header.h> +#include <libubigen.h> +#include <libiniparser.h> +#include "common.h" + +#define PROGRAM_VERSION "1.5" +#define PROGRAM_NAME "ubinize" + +static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION +" - a tool to generate UBI images. An UBI image may contain one or more UBI " +"volumes which have to be defined in the input configuration ini-file. The " +"ini file defines all the UBI volumes - their characteristics and the and the " +"contents, but it does not define the characteristics of the flash the UBI " +"image is generated for. Instead, the flash characteristics are defined via " +"the comman-line options. " +"Note, if not sure about some of the command-line parameters, do not specify " +"them and let the utility to use default values."; + +static const char *optionsstr = +"-o, --output=<file name> output file name (default is stdout)\n" +"-p, --peb-size=<bytes> size of the physical eraseblock of the flash\n" +" this UBI image is created for in bytes,\n" +" kilobytes (KiB), or megabytes (MiB)\n" +" (mandatory parameter)\n" +"-m, --min-io-size=<bytes> minimum input/output unit size of the flash\n" +" in bytes\n" +"-s, --sub-page-size=<bytes> minimum input/output unit used for UBI\n" +" headers, e.g. sub-page size in case of NAND\n" +" flash (equivalent to the minimum input/output\n" +" unit size by default)\n" +"-O, --vid-hdr-offset=<num> offset if the VID header from start of the\n" +" physical eraseblock (default is the second\n" +" minimum I/O unit or sub-page, if it was\n" +" specified)\n" +"-e, --erase-counter=<num> the erase counter value to put to EC headers\n" +" (default is 0)\n" +"-x, --ubi-ver=<num> UBI version number to put to EC headers\n" +" (default is 1)\n" +"-v --verbose be verbose\n" +"-h, --help print help message\n" +"-V, --version print program version"; + +static const char *usage = +"Usage: " PROGRAM_NAME " [-o filename] [-h] [-V] [--output=<filename>] [--help]\n" +"\t\t[--version] inifile\n" +"Example: " PROGRAM_NAME "-o fs.raw cfg.ini"; + +struct option long_options[] = { + { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' }, + { .name = "peb-size", .has_arg = 1, .flag = NULL, .val = 'p' }, + { .name = "min-io-size", .has_arg = 1, .flag = NULL, .val = 'm' }, + { .name = "sub-page-size", .has_arg = 1, .flag = NULL, .val = 's' }, + { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' }, + { .name = "erase-counter", .has_arg = 1, .flag = NULL, .val = 'e' }, + { .name = "ubi-ver", .has_arg = 1, .flag = NULL, .val = 'x' }, + { .name = "verbose", .has_arg = 1, .flag = NULL, .val = 'v' }, + { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, + { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, + { NULL, 0, NULL, 0} +}; + +struct args { + const char *f_in; + const char *f_out; + FILE *fp_out; + int peb_size; + int min_io_size; + int subpage_size; + int vid_hdr_offs; + int ec; + int ubi_ver; + int verbose; + dictionary *dict; +}; + +static struct args args = { + .f_out = NULL, + .peb_size = -1, + .min_io_size = -1, + .subpage_size = -1, + .vid_hdr_offs = 0, + .ec = 0, + .ubi_ver = 1, + .verbose = 0, +}; + +static int parse_opt(int argc, char * const argv[]) +{ + while (1) { + int key; + char *endp; + + key = getopt_long(argc, argv, "o:p:m:s:O:e:x:vhV", long_options, NULL); + if (key == -1) + break; + + switch (key) { + case 'o': + args.fp_out = fopen(optarg, "wb"); + if (!args.fp_out) { + errmsg("cannot open file \"%s\"", optarg); + return -1; + } + args.f_out = optarg; + break; + + case 'p': + args.peb_size = strtoull(optarg, &endp, 0); + if (endp == optarg || args.peb_size <= 0) { + errmsg("bad physical eraseblock size: \"%s\"", optarg); + return -1; + } + if (*endp != '\0') { + int mult = ubiutils_get_multiplier(endp); + + if (mult == -1) { + errmsg("bad size specifier: \"%s\" - " + "should be 'KiB', 'MiB' or 'GiB'", endp); + return -1; + } + args.peb_size *= mult; + } + break; + + case 'm': + args.min_io_size = strtoull(optarg, &endp, 0); + if (endp == optarg || args.min_io_size <= 0) { + errmsg("bad min. I/O unit size: \"%s\"", optarg); + return -1; + } + if (*endp != '\0') { + int mult = ubiutils_get_multiplier(endp); + + if (mult == -1) { + errmsg("bad size specifier: \"%s\" - " + "should be 'KiB', 'MiB' or 'GiB'", endp); + return -1; + } + args.min_io_size *= mult; + } + break; + + case 's': + args.subpage_size = strtoull(optarg, &endp, 0); + if (endp == optarg || args.subpage_size <= 0) { + errmsg("bad sub-page size: \"%s\"", optarg); + return -1; + } + if (*endp != '\0') { + int mult = ubiutils_get_multiplier(endp); + + if (mult == -1) { + errmsg("bad size specifier: \"%s\" - " + "should be 'KiB', 'MiB' or 'GiB'", endp); + return -1; + } + args.subpage_size *= mult; + } + break; + + case 'O': + args.vid_hdr_offs = strtoul(optarg, &endp, 0); + if (endp == optarg || args.vid_hdr_offs < 0) { + errmsg("bad VID header offset: \"%s\"", optarg); + return -1; + } + break; + + case 'e': + args.ec = strtoul(optarg, &endp, 0); + if (endp == optarg || args.ec < 0) { + errmsg("bad erase counter value: \"%s\"", optarg); + return -1; + } + break; + + case 'x': + args.ubi_ver = strtoul(optarg, &endp, 0); + if (endp == optarg || args.ubi_ver < 0) { + errmsg("bad UBI version: \"%s\"", optarg); + return -1; + } + break; + + case 'v': + args.verbose = 1; + break; + + case 'h': + ubiutils_print_text(stderr, doc, 80); + fprintf(stderr, "\n\n%s\n\n", usage); + fprintf(stderr, "%s\n", optionsstr); + exit(EXIT_SUCCESS); + + case 'V': + fprintf(stderr, "%s\n", PROGRAM_VERSION); + exit(EXIT_SUCCESS); + + default: + fprintf(stderr, "Use -h for help\n"); + return -1; + } + } + + if (optind == argc) { + errmsg("input PFI file was not specified (use -h for help)"); + return -1; + } + + if (optind != argc - 1) { + errmsg("more then one input PFI file was specified (use -h for help)"); + return -1; + } + + args.f_in = argv[optind]; + + if (args.peb_size < 0) { + errmsg("physical eraseblock size was not specified (use -h for help)"); + return -1; + } + + if (args.min_io_size < 0) { + errmsg("min. I/O unit size was not specified (use -h for help)"); + return -1; + } + + if (args.subpage_size < 0) + args.subpage_size = args.min_io_size; + + if (!args.f_out) { + args.f_out = "stdout"; + args.fp_out = stdout; + } + + return 0; +} + +int read_section(const char *sname, struct ubigen_vol_info *vi, + const char **img) +{ + char buf[256]; + const char *p; + + *img = NULL; + + if (strlen(sname) > 128) { + errmsg("too long section name \"%s\"", sname); + return -1; + } + + /* Make sure mode is UBI, otherwise ignore this section */ + sprintf(buf, "%s:mode", sname); + p = iniparser_getstring(args.dict, buf, NULL); + if (!p) { + errmsg("\"mode\" key not found in section \"%s\"", sname); + errmsg("the \"mode\" key is mandatory and has to be " + "\"mode=ubi\" if the section describes an UBI volume"); + return -1; + } + + /* If mode is not UBI, skip this section */ + if (strcmp(p, "ubi")) { + verbose(args.verbose, "skip non-ubi section \"%s\"", sname); + return 1; + } + + verbose(args.verbose, "mode=ubi, keep parsing"); + + /* Fetch the name of the volume image file */ + sprintf(buf, "%s:image", sname); + p = iniparser_getstring(args.dict, buf, NULL); + if (p) + *img = p; + + /* Fetch volume id */ + sprintf(buf, "%s:vol_id", sname); + vi->id = iniparser_getint(args.dict, buf, -1); + if (vi->id == -1) { + errmsg("\"vol_id\" key not found in section \"%s\"", sname); + return -1; + } + + if (vi->id < 0) { + errmsg("negative volume ID %d", vi->id); + return -1; + } + + if (vi->id >= UBI_MAX_VOLUMES) { + errmsg("too highe volume ID %d, max. is %d", + vi->id, UBI_MAX_VOLUMES); + return -1; + } + + verbose(args.verbose, "volume ID: %d", vi->id); + + /* Fetch volume size */ + sprintf(buf, "%s:vol_size", sname); + p = iniparser_getstring(args.dict, buf, NULL); + if (p) { + char *endp; + + vi->bytes = strtoull((char *)p, &endp, 0); + if (endp == p || vi->bytes <= 0) { + errmsg("bad \"vol_size\" key: \"%s\"", p); + return -1; + } + + if (*endp != '\0') { + int mult = ubiutils_get_multiplier(endp); + + if (mult == -1) { + errmsg("bad size specifier: \"%s\" - " + "should be 'KiB', 'MiB' or 'GiB'", endp); + return -1; + } + vi->bytes *= mult; + } + + verbose(args.verbose, "volume size: %lld bytes", vi->bytes); + } else { + struct stat st; + + if (!*img) { + errmsg("neither image file (\"image=\") nor volume size" + " (\"vol_size=\") specified"); + return -1; + } + + if (stat(*img, &st)) { + errmsg("cannot stat \"%s\"", *img); + perror("stat"); + return -1; + } + + vi->bytes = st.st_size; + + if (vi->bytes == 0) { + errmsg("file \"%s\" referred from section \"%s\" is empty", + *img, sname); + return -1; + } + + printf(PROGRAM_NAME ": volume size was not specified in" + "section \"%s\", assume ", sname); + ubiutils_print_bytes(vi->bytes, 1); + printf("\n"); + } + + /* Fetch volume type */ + sprintf(buf, "%s:vol_type", sname); + p = iniparser_getstring(args.dict, buf, NULL); + if (!p) { + normsg(": volume type was not specified in " + "section \"%s\", assume \"dynamic\"\n", sname); + vi->type = UBI_VID_DYNAMIC; + } else { + if (!strcmp(p, "static")) + vi->type = UBI_VID_STATIC; + else if (!strcmp(p, "dynamic")) + vi->type = UBI_VID_DYNAMIC; + else { + errmsg("invalid volume type \"%s\"", p); + return -1; + } + } + + verbose(args.verbose, "volume type: %s", + vi->type == UBI_VID_DYNAMIC ? "dynamic" : "static"); + + /* Fetch volume name */ + sprintf(buf, "%s:vol_name", sname); + p = iniparser_getstring(args.dict, buf, NULL); + if (!p) { + errmsg("\"vol_name\" key not found in section \"%s\"", sname); + return -1; + } + + vi->name = p; + vi->name_len = strlen(p); + if (vi->name_len > UBI_VOL_NAME_MAX) { + errmsg("too long volume name in section \"%s\", max. is " + "%d characters", vi->name, UBI_VOL_NAME_MAX); + return -1; + } + + verbose(args.verbose, "volume name: %s", p); + + /* Fetch volume alignment */ + sprintf(buf, "%s:vol_alignment", sname); + vi->alignment = iniparser_getint(args.dict, buf, -1); + if (vi->alignment == -1) { + normsg("volume alignment was not specified in section " + "\"%s\", assume 1", sname); + vi->alignment = 1; + } else if (vi->id < 0) { + errmsg("negative volume alignement %d", vi->alignment); + return -1; + } + + verbose(args.verbose, "volume alignment: %d", vi->alignment); + + return 0; +} + +static void init_vol_info(const struct ubigen_info *ui, + struct ubigen_vol_info *vi) +{ + vi->data_pad = ui->leb_size % vi->alignment; + vi->usable_leb_size = ui->leb_size - vi->data_pad; + vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size; + vi->compat = 0; +} + +int main(int argc, char * const argv[]) +{ + int err = -1, sects, i, volumes; + struct ubigen_info ui; + struct ubi_vtbl_record *vtbl; + + err = parse_opt(argc, argv); + if (err) + return -1; + + ubigen_info_init(&ui, args.peb_size, args.min_io_size, + args.subpage_size, args.vid_hdr_offs, + args.ubi_ver, args.ec); + + verbose(args.verbose, "LEB size: %d", ui.leb_size); + verbose(args.verbose, "PEB size: %d", ui.peb_size); + verbose(args.verbose, "min_io_size: %d", ui.min_io_size); + verbose(args.verbose, "VID offset: %d", ui.vid_hdr_offs); + + vtbl = ubigen_create_empty_vtbl(&ui); + if (!vtbl) + goto out; + + args.dict = iniparser_load(args.f_in); + if (!args.dict) { + errmsg("cannot load the input ini file \"%s\"", args.f_in); + goto out_vtbl; + } + + verbose(args.verbose, "loaded the ini-file \"%s\"", args.f_in); + + /* Each section describes one volume */ + sects = iniparser_getnsec(args.dict); + if (sects == -1) { + errmsg("ini-file parsing error (iniparser_getnsec)"); + goto out_dict; + } + + verbose(args.verbose, "count of sections: %d", sects); + if (sects == 0) { + errmsg("no sections found the ini-file \"%s\"", args.f_in); + goto out_dict; + } + + /* + * Skip 2 PEBs at the beginning of the file for the volume table which + * will be written later. + */ + if (fseek(args.fp_out, ui.peb_size * 2, SEEK_SET) == -1) { + errmsg("cannot seek file \"%s\"", args.f_out); + goto out_dict; + } + + for (i = 0; i < sects; i++) { + const char *sname = iniparser_getsecname(args.dict, i); + struct ubigen_vol_info vi; + const char *img = NULL; + struct stat st; + FILE *f; + + if (!sname) { + errmsg("ini-file parsing error (iniparser_getsecname)"); + goto out_dict; + } + + if (args.verbose) + printf("\n"); + verbose(args.verbose, "parsing section \"%s\"", sname); + + err = read_section(sname, &vi, &img); + if (err == -1) + goto out_dict; + if (!err) + volumes += 1; + init_vol_info(&ui, &vi); + + verbose(args.verbose, "adding volume %d", vi.id); + + err = ubigen_add_volume(&ui, &vi, vtbl); + if (err) { + errmsg("cannot add volume for section \"%s\"", sname); + goto out_dict; + } + + if (!img) + continue; + + if (stat(img, &st)) { + errmsg("cannot stat \"%s\"", img); + perror("stat"); + goto out_dict; + } + + f = fopen(img, "r"); + if (!f) { + errmsg("cannot open \"%s\"", img); + perror("fopen"); + goto out_dict; + } + + verbose(args.verbose, "writing volume %d", vi.id); + verbose(args.verbose, "image file: %s", img); + + err = ubigen_write_volume(&ui, &vi, st.st_size, f, args.fp_out); + fclose(f); + if (err) { + errmsg("cannot write volume for section \"%s\"", sname); + goto out_dict; + } + + if (args.verbose) + printf("\n"); + } + + verbose(args.verbose, "writing layout volume"); + + err = ubigen_write_layout_vol(&ui, vtbl, args.fp_out); + if (err) { + errmsg("cannot write layout volume"); + goto out_dict; + } + + verbose(args.verbose, "done"); + + iniparser_freedict(args.dict); + free(vtbl); + fclose(args.fp_out); + return 0; + +out_dict: + iniparser_freedict(args.dict); +out_vtbl: + free(vtbl); +out: + fclose(args.fp_out); + remove(args.f_out); + return err; +} + +#if 0 +/** + * 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 void pfi2vol_info(const struct pfi_ubi *pfi, int n, + struct ubigen_vol_info *vi, + const struct ubigen_info *ui) +{ + 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; + } + + vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size; + vi->compat = 0; +} +#endif diff --git a/ubi-utils/src/unubi.c b/ubi-utils/src/unubi.c deleted file mode 100644 index 1d4b35b..0000000 --- a/ubi-utils/src/unubi.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006, 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Authors: Drake Dowsett, dowsett@de.ibm.com - * Frank Haverkamp, haver@vnet.ibm.com - * - * 1.2 Removed argp because we want to use uClibc. - * 1.3 Minor cleanups. - * 1.4 Meanwhile Drake had done a lot of changes, syncing those. - * 1.5 Bugfixes, simplifications - */ - -/* - * unubi reads an image file containing blocks of UBI headers and data - * (such as produced from nand2bin) and rebuilds the volumes within. The - * default operation (when no flags are given) is to rebuild all valid - * volumes found in the image. unubi can also read straight from the - * onboard MTD device (ex. /dev/mtdblock/NAND). - */ - -/* TODO: consideration for dynamic vs. static volumes */ - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdint.h> -#include <getopt.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <limits.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <mtd/ubi-header.h> - -#include "crc32.h" -#include "unubi_analyze.h" - -#define EXEC "unubi" -#define CONTACT "haver@vnet.ibm.com" -#define VERSION "1.5" - -static char doc[] = "\nVersion: " VERSION "\n"; -static int debug = 0; - -static const char *optionsstr = -"Extract volumes and/or analysis information from an UBI data file.\n" -"When no parameters are flagged or given, the default operation is\n" -"to rebuild all valid complete UBI volumes found within the image.\n" -"\n" -" OPERATIONS\n" -" -a, --analyze Analyze image and create gnuplot graphs\n" -" -i, --info-table Extract volume information tables\n" -" -r, --rebuild=<volume-id> Extract and rebuild volume\n" -"\n" -" OPTIONS\n" -" -b, --blocksize=<block-size> Specify size of eraseblocks in image in bytes\n" -" (default 128KiB)\n" -" -d, --dir=<output-dir> Specify output directory\n" -" -D, --debug Enable debug output\n" -" -s, --headersize=<header-size> Specify size reserved for metadata in eraseblock\n" - " in bytes (default 2048 Byte)\n" - /* the -s option might be insufficient when using different vid - offset than what we used when writing this tool ... Better would - probably be --vid-hdr-offset or alike */ -"\n" -" ADVANCED\n" -" -e, --eb-split Generate individual eraseblock images (all\n" -" eraseblocks)\n" -" -v, --vol-split Generate individual eraseblock images (valid\n" -" eraseblocks only)\n" -" -V, --vol-split! Raw split by eraseblock (valid eraseblocks only)\n" -"\n" -" -?, --help Give this help list\n" -" --usage Give a short usage message\n" -" --version Print program version\n" -"\n"; - -static const char *usage = -"Usage: unubi [-aievV?] [-r <volume-id>] [-b <block-size>] [-d <output-dir>]\n" -" [-s <header-size>] [--analyze] [--info-table]\n" -" [--rebuild=<volume-id>] [--blocksize=<block-size>]\n" -" [--dir=<output-dir>] [--headersize=<header-size>] [--eb-split]\n" -" [--vol-split] [--vol-split!] [--help] [--usage] [--version]\n" -" image-file\n"; - -#define ERR_MSG(fmt...) \ - fprintf(stderr, EXEC ": " fmt) - -#define SPLIT_DATA 1 -#define SPLIT_RAW 2 - -#define DIR_FMT "unubi_%s" -#define KIB 1024 -#define MIB (KIB * KIB) -#define MAXPATH KIB - -/* filenames */ -#define FN_INVAL "%s/eb%04u%s" /* invalid eraseblock */ -#define FN_NSURE "%s/eb%04u_%03u_%03u_%03x%s" /* unsure eraseblock */ -#define FN_VALID "%s/eb%04u_%03u_%03u_%03x%s" /* valid eraseblock */ -#define FN_VOLSP "%s/vol%03u_%03u_%03u_%04u" /* split volume */ -#define FN_VOLWH "%s/volume%03u" /* whole volume */ -#define FN_VITBL "%s/vol_info_table%u" /* vol info table */ - -/* struct args: - * bsize int, blocksize of image blocks - * hsize int, eraseblock header size - * analyze flag, when non-zero produce analysis - * eb_split flag, when non-zero output eb#### - * note: SPLIT_DATA vs. SPLIT_RAW - * vol_split flag, when non-zero output vol###_#### - * note: SPLIT_DATA vs. SPLIT_RAW - * odir_path string, directory to place volumes in - * img_path string, file to read as ubi image - * vols int array of size UBI_MAX_VOLUMES, where a 1 can be - * written for each --rebuild flag in the index specified - * then the array can be counted and collapsed using - * count_set() and collapse() - */ -struct args { - int analyze; - int itable; - uint32_t *vols; - - size_t vid_hdr_offset; - size_t data_offset; - size_t bsize; /* FIXME replace by vid_hdr/data offs? */ - size_t hsize; - - char *odir_path; - int eb_split; - int vol_split; - char *img_path; - - char **options; -}; - -struct option long_options[] = { - { .name = "rebuild", .has_arg = 1, .flag = NULL, .val = 'r' }, - { .name = "dir", .has_arg = 1, .flag = NULL, .val = 'd' }, - { .name = "analyze", .has_arg = 0, .flag = NULL, .val = 'a' }, - { .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'b' }, - { .name = "eb-split", .has_arg = 0, .flag = NULL, .val = 'e' }, - { .name = "vol-split", .has_arg = 0, .flag = NULL, .val = 'v' }, - { .name = "vol-split!", .has_arg = 0, .flag = NULL, .val = 'e' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = '?' }, - { .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'J' }, - { NULL, 0, NULL, 0} -}; - -/** - * parses out a numerical value from a string of numbers followed by: - * k, K, kib, KiB for kibibyte - * m, M, mib, MiB for mebibyte - **/ -static uint32_t -str_to_num(char *str) -{ - char *s; - ulong num; - - s = str; - num = strtoul(s, &s, 0); - - if (*s != '\0') { - if ((strcmp(s, "KiB") == 0) || (strcmp(s, "K") == 0) || - (strcmp(s, "kib") == 0) || (strcmp(s, "k") == 0)) - num *= KIB; - else if ((strcmp(s, "MiB") == 0) || (strcmp(s, "M") == 0) || - (strcmp(s, "mib") == 0) || (strcmp(s, "m") == 0)) - num *= MIB; - else - ERR_MSG("couldn't parse '%s', assuming %lu\n", - s, num); - } - return num; -} - -static int -parse_opt(int argc, char **argv, struct args *args) -{ - uint32_t i; - - while (1) { - int key; - - key = getopt_long(argc, argv, "ab:s:d:Deir:vV?J", - long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'a': /* --analyze */ - args->analyze = 1; - break; - case 'b': /* --block-size=<block-size> */ - args->bsize = str_to_num(optarg); - break; - case 's': /* --header-size=<header-size> */ - args->hsize = str_to_num(optarg); - break; - case 'd': /* --dir=<output-dir> */ - args->odir_path = optarg; - break; - case 'D': /* --debug */ - /* I wanted to use -v but that was already - used ... */ - debug = 1; - break; - case 'e': /* --eb-split */ - args->eb_split = SPLIT_RAW; - break; - case 'i': /* --info-table */ - args->itable = 1; - break; - case 'r': /* --rebuild=<volume-id> */ - i = str_to_num(optarg); - if (i < UBI_MAX_VOLUMES) - args->vols[str_to_num(optarg)] = 1; - else { - ERR_MSG("volume-id out of bounds\n"); - return -1; - } - break; - case 'v': /* --vol-split */ - if (args->vol_split != SPLIT_RAW) - args->vol_split = SPLIT_DATA; - break; - case 'V': /* --vol-split! */ - args->vol_split = SPLIT_RAW; - break; - case '?': /* help */ - fprintf(stderr, "Usage: unubi [OPTION...] " - "image-file\n%s%s\nReport bugs to %s\n", - doc, optionsstr, CONTACT); - exit(0); - break; - case 'J': - fprintf(stderr, "%s\n", VERSION); - exit(0); - break; - default: - fprintf(stderr, "%s", usage); - exit(-1); - } - } - - /* FIXME I suppose hsize should be replaced! */ - args->vid_hdr_offset = args->hsize - UBI_VID_HDR_SIZE; - args->data_offset = args->hsize; - - if (optind < argc) - args->img_path = argv[optind++]; - return 0; -} - - -/** - * counts the number of indicies which are flagged in full_array; - * full_array is an array of flags (1/0); - **/ -static size_t -count_set(uint32_t *full_array, size_t full_len) -{ - size_t count, i; - - if (full_array == NULL) - return 0; - - for (i = 0, count = 0; i < full_len; i++) - if (full_array[i] != 0) - count++; - - return count; -} - - -/** - * generates coll_array from full_array; - * full_array is an array of flags (1/0); - * coll_array is an array of the indicies in full_array which are flagged (1); - **/ -static size_t -collapse(uint32_t *full_array, size_t full_len, - uint32_t *coll_array, size_t coll_len) -{ - size_t i, j; - - if ((full_array == NULL) || (coll_array == NULL)) - return 0; - - for (i = 0, j = 0; (i < full_len) && (j < coll_len); i++) - if (full_array[i] != 0) { - coll_array[j] = i; - j++; - } - - return j; -} - -/** - * data_crc: save the FILE* position, calculate the crc over a span, - * reset the position - * returns non-zero when EOF encountered - **/ -static int -data_crc(FILE* fpin, size_t length, uint32_t *ret_crc) -{ - int rc; - size_t i; - char buf[length]; - uint32_t crc; - fpos_t start; - - rc = fgetpos(fpin, &start); - if (rc < 0) - return -1; - - for (i = 0; i < length; i++) { - int c = fgetc(fpin); - if (c == EOF) { - ERR_MSG("unexpected EOF\n"); - return -1; - } - buf[i] = (char)c; - } - - rc = fsetpos(fpin, &start); - if (rc < 0) - return -1; - - crc = crc32(UBI_CRC32_INIT, buf, length); - *ret_crc = crc; - return 0; -} - - -/** - * reads data of size len from fpin and writes it to path - **/ -static int -extract_data(FILE* fpin, size_t len, const char *path) -{ - int rc; - size_t i; - FILE* fpout; - - rc = 0; - fpout = NULL; - - fpout = fopen(path, "wb"); - if (fpout == NULL) { - ERR_MSG("couldn't open file for writing: %s\n", path); - rc = -1; - goto err; - } - - for (i = 0; i < len; i++) { - int c = fgetc(fpin); - if (c == EOF) { - ERR_MSG("unexpected EOF while writing: %s\n", path); - rc = -2; - goto err; - } - c = fputc(c, fpout); - if (c == EOF) { - ERR_MSG("couldn't write: %s\n", path); - rc = -3; - goto err; - } - } - - err: - if (fpout != NULL) - fclose(fpout); - return rc; -} - - -/** - * extract volume information table from block. saves and reloads fpin - * position - * returns -1 when a fpos set or get fails, otherwise <= -2 on other - * failure and 0 on success - **/ -static int -extract_itable(FILE *fpin, struct eb_info *cur, size_t bsize, size_t num, - const char *path) -{ - char filename[MAXPATH + 1]; - int rc; - size_t i, max; - fpos_t temp; - FILE* fpout = NULL; - struct ubi_vtbl_record rec; - - if (fpin == NULL || cur == NULL || path == NULL) - return -2; - - /* remember position */ - rc = fgetpos(fpin, &temp); - if (rc < 0) - return -1; - - /* jump to top of eraseblock, skip to data section */ - fsetpos(fpin, &cur->eb_top); - if (rc < 0) - return -1; - fseek(fpin, __be32_to_cpu(cur->ec.data_offset), SEEK_CUR); - - /* prepare output file */ - if (__be32_to_cpu(cur->vid.vol_id) != UBI_LAYOUT_VOL_ID) - return -2; - memset(filename, 0, MAXPATH + 1); - snprintf(filename, MAXPATH, FN_VITBL, path, num); - fpout = fopen(filename, "w"); - if (fpout == NULL) - return -2; - - /* loop through entries */ - fprintf(fpout, - "index\trpebs\talign\ttype\tcrc\t\tname\n"); - max = bsize - __be32_to_cpu(cur->ec.data_offset); - for (i = 0; i < (max / sizeof(rec)); i++) { - int blank = 1; - char *ptr, *base; - char name[UBI_VOL_NAME_MAX + 1]; - const char *type = "unknown\0"; - uint32_t crc; - - /* read record */ - rc = fread(&rec, 1, sizeof(rec), fpin); - if (rc == 0) - break; - if (rc != sizeof(rec)) { - ERR_MSG("reading volume information " - "table record failed\n"); - rc = -3; - goto exit; - } - - /* check crc */ - crc = crc32(UBI_CRC32_INIT, &rec, UBI_VTBL_RECORD_SIZE_CRC); - if (crc != __be32_to_cpu(rec.crc)) - continue; - - /* check for empty */ - base = (char *)&rec; - ptr = base; - while (blank && - ((unsigned)(ptr - base) < UBI_VTBL_RECORD_SIZE_CRC)) { - if (*ptr != 0) - blank = 0; - ptr++; - } - - if (blank) - continue; - - /* prep type string */ - if (rec.vol_type == UBI_VID_DYNAMIC) - type = "dynamic\0"; - else if (rec.vol_type == UBI_VID_STATIC) - type = "static\0"; - - /* prep name string */ - rec.name[__be16_to_cpu(rec.name_len)] = '\0'; - sprintf(name, "%s", rec.name); - - /* print record line to fpout */ - fprintf(fpout, "%u\t%u\t%u\t%s\t0x%08x\t%s\n", - i, - __be32_to_cpu(rec.reserved_pebs), - __be32_to_cpu(rec.alignment), - type, - __be32_to_cpu(rec.crc), - name); - } - - exit: - /* reset position */ - if (fsetpos(fpin, &temp) < 0) - rc = -1; - - if (fpout != NULL) - fclose(fpout); - - return rc; -} - - -/** - * using eb chain, tries to rebuild the data of volume at vol_id, or for all - * the known volumes, if vol_id is NULL; - **/ -static int -rebuild_volume(FILE * fpin, uint32_t *vol_id, struct eb_info **head, - const char *path, size_t block_size, size_t header_size) -{ - char filename[MAXPATH]; - int rc; - uint32_t vol, num, data_size; - FILE* fpout; - struct eb_info *cur; - - rc = 0; - - if ((fpin == NULL) || (head == NULL) || (*head == NULL)) - return 0; - - /* when vol_id is null, then do all */ - if (vol_id == NULL) { - cur = *head; - vol = __be32_to_cpu(cur->vid.vol_id); - } else { - vol = *vol_id; - eb_chain_position(head, vol, NULL, &cur); - if (cur == NULL) { - if (debug) - ERR_MSG("no valid volume %d was found\n", vol); - return -1; - } - } - - num = 0; - snprintf(filename, MAXPATH, FN_VOLWH, path, vol); - fpout = fopen(filename, "wb"); - if (fpout == NULL) { - ERR_MSG("couldn't open file for writing: %s\n", filename); - return -1; - } - - while (cur != NULL) { - size_t i; - - if (__be32_to_cpu(cur->vid.vol_id) != vol) { - /* close out file */ - fclose(fpout); - - /* only stay around if that was the only volume */ - if (vol_id != NULL) - goto out; - - /* begin with next */ - vol = __be32_to_cpu(cur->vid.vol_id); - num = 0; - snprintf(filename, MAXPATH, FN_VOLWH, path, vol); - fpout = fopen(filename, "wb"); - if (fpout == NULL) { - ERR_MSG("couldn't open file for writing: %s\n", - filename); - return -1; - } - } - - while (num < __be32_to_cpu(cur->vid.lnum)) { - /* FIXME haver: I hope an empty block is - written out so that the binary has no holes - ... */ - if (debug) - ERR_MSG("missing valid block %d for volume %d\n", - num, vol); - num++; - } - - rc = fsetpos(fpin, &(cur->eb_top)); - if (rc < 0) - goto out; - fseek(fpin, __be32_to_cpu(cur->ec.data_offset), SEEK_CUR); - - if (cur->vid.vol_type == UBI_VID_DYNAMIC) - /* FIXME It might be that alignment has influence */ - data_size = block_size - header_size; - else - data_size = __be32_to_cpu(cur->vid.data_size); - - for (i = 0; i < data_size; i++) { - int c = fgetc(fpin); - if (c == EOF) { - ERR_MSG("unexpected EOF while writing: %s\n", - filename); - rc = -2; - goto out; - } - c = fputc(c, fpout); - if (c == EOF) { - ERR_MSG("couldn't write: %s\n", filename); - rc = -3; - goto out; - } - } - - cur = cur->next; - num++; - } - - out: - if (vol_id == NULL) - fclose(fpout); - return rc; -} - - -/** - * traverses FILE* trying to load complete, valid and accurate header data - * into the eb chain; - **/ -static int -unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a) -{ - char filename[MAXPATH + 1]; - char reason[MAXPATH + 1]; - int rc; - size_t i, count, itable_num; - /* relations: - * cur ~ head - * next ~ first */ - struct eb_info *head, *cur, *first, *next; - struct eb_info **next_ptr; - - rc = 0; - count = 0; - itable_num = 0; - head = NULL; - first = NULL; - next = NULL; - cur = malloc(sizeof(*cur)); - if (cur == NULL) { - ERR_MSG("out of memory\n"); - rc = -ENOMEM; - goto err; - } - memset(cur, 0, sizeof(*cur)); - - fgetpos(fpin, &(cur->eb_top)); - while (1) { - const char *raw_path; - uint32_t crc; - - cur->phys_addr = ftell(fpin); - cur->phys_block = cur->phys_addr / a->bsize; - cur->data_crc_ok = 0; - cur->ec_crc_ok = 0; - cur->vid_crc_ok = 0; - - memset(filename, 0, MAXPATH + 1); - memset(reason, 0, MAXPATH + 1); - - /* in case of an incomplete ec header */ - raw_path = FN_INVAL; - - /* read erasecounter header */ - rc = fread(&cur->ec, 1, sizeof(cur->ec), fpin); - if (rc == 0) - goto out; /* EOF */ - if (rc != sizeof(cur->ec)) { - ERR_MSG("reading ec-hdr failed\n"); - rc = -1; - goto err; - } - - /* check erasecounter header magic */ - if (__be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) { - snprintf(reason, MAXPATH, ".invalid.ec_magic"); - goto invalid; - } - - /* check erasecounter header crc */ - crc = 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; - } - - /* read volume id header */ - rc = fsetpos(fpin, &(cur->eb_top)); - if (rc != 0) - goto err; - fseek(fpin, __be32_to_cpu(cur->ec.vid_hdr_offset), SEEK_CUR); - rc = fread(&cur->vid, 1, sizeof(cur->vid), fpin); - if (rc == 0) - goto out; /* EOF */ - if (rc != sizeof(cur->vid)) { - ERR_MSG("reading vid-hdr failed\n"); - rc = -1; - goto err; - } - - /* if the magic number is 0xFFFFFFFF, then it's very likely - * that the volume is empty */ - if (__be32_to_cpu(cur->vid.magic) == 0xffffffff) { - snprintf(reason, MAXPATH, ".empty"); - goto invalid; - } - - /* vol_id should be in bounds */ - if ((__be32_to_cpu(cur->vid.vol_id) >= UBI_MAX_VOLUMES) && - (__be32_to_cpu(cur->vid.vol_id) < - UBI_INTERNAL_VOL_START)) { - snprintf(reason, MAXPATH, ".invalid"); - goto invalid; - } else - raw_path = FN_NSURE; - - /* check volume id header magic */ - if (__be32_to_cpu(cur->vid.magic) != UBI_VID_HDR_MAGIC) { - snprintf(reason, MAXPATH, ".invalid.vid_magic"); - goto invalid; - } - cur->ec_crc_ok = 1; - - /* check volume id header crc */ - crc = 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; - } - cur->vid_crc_ok = 1; - - /* check data crc, but only for a static volume */ - if (cur->vid.vol_type == UBI_VID_STATIC) { - rc = data_crc(fpin, __be32_to_cpu(cur->vid.data_size), - &crc); - if (rc < 0) - goto err; - if (__be32_to_cpu(cur->vid.data_crc) != crc) { - snprintf(reason, MAXPATH, ".invalid.data_crc"); - goto invalid; - } - cur->data_crc_ok = 1; - } - - /* enlist this vol, it's valid */ - raw_path = FN_VALID; - cur->linear = count; - rc = eb_chain_insert(&head, cur); - if (rc < 0) { - if (rc == -ENOMEM) { - ERR_MSG("out of memory\n"); - goto err; - } - ERR_MSG("unknown and unexpected error, please contact " - CONTACT "\n"); - goto err; - } - - /* extract info-table */ - if (a->itable && - (__be32_to_cpu(cur->vid.vol_id) == UBI_LAYOUT_VOL_ID)) { - extract_itable(fpin, cur, a->bsize, - itable_num, a->odir_path); - itable_num++; - } - - /* split volumes */ - if (a->vol_split) { - size_t size = 0; - - rc = fsetpos(fpin, &(cur->eb_top)); - if (rc != 0) - goto err; - - /* - * FIXME For dynamic UBI volumes we must write - * the maximum available data. The - * vid.data_size field is not used in this - * case. The dynamic volume user is - * responsible for the content. - */ - if (a->vol_split == SPLIT_DATA) { - /* Write only data section */ - if (cur->vid.vol_type == UBI_VID_DYNAMIC) { - /* FIXME Formular is not - always right ... */ - size = a->bsize - a->hsize; - } else - size = __be32_to_cpu(cur->vid.data_size); - - fseek(fpin, - __be32_to_cpu(cur->ec.data_offset), - SEEK_CUR); - } - else if (a->vol_split == SPLIT_RAW) - /* write entire eraseblock */ - size = a->bsize; - - snprintf(filename, MAXPATH, FN_VOLSP, - a->odir_path, - __be32_to_cpu(cur->vid.vol_id), - __be32_to_cpu(cur->vid.lnum), - __be32_to_cpu(cur->vid.leb_ver), count); - rc = extract_data(fpin, size, filename); - if (rc < 0) - goto err; - } - - invalid: - /* split eraseblocks */ - if (a->eb_split) { - /* jump to top of block */ - rc = fsetpos(fpin, &(cur->eb_top)); - if (rc != 0) - goto err; - - if (strcmp(raw_path, FN_INVAL) == 0) - snprintf(filename, MAXPATH, raw_path, - a->odir_path, count, reason); - else - snprintf(filename, MAXPATH, raw_path, - a->odir_path, - count, - __be32_to_cpu(cur->vid.vol_id), - __be32_to_cpu(cur->vid.lnum), - __be32_to_cpu(cur->vid.leb_ver), - reason); - - rc = extract_data(fpin, a->bsize, filename); - if (rc < 0) - goto err; - } - - /* append to simple linked list */ - if (first == NULL) - next_ptr = &first; - else - next_ptr = &next->next; - - *next_ptr = malloc(sizeof(**next_ptr)); - if (*next_ptr == NULL) { - ERR_MSG("out of memory\n"); - rc = -ENOMEM; - goto err; - } - memset(*next_ptr, 0, sizeof(**next_ptr)); - - next = *next_ptr; - memcpy(next, cur, sizeof(*next)); - next->next = NULL; - - count++; - rc = fsetpos(fpin, &(cur->eb_top)); - if (rc != 0) - goto err; - fseek(fpin, a->bsize, SEEK_CUR); - memset(cur, 0, sizeof(*cur)); - - fgetpos(fpin, &(cur->eb_top)); - } - - out: - for (i = 0; i < vc; i++) { - rc = rebuild_volume(fpin, &vols[i], &head, a->odir_path, - a->bsize, a->hsize); - if (rc < 0) - goto err; - } - - /* if there were no volumes specified, rebuild them all, - * UNLESS eb_ or vol_ split or analyze was specified */ - if ((vc == 0) && (!a->eb_split) && (!a->vol_split) && - (!a->analyze) && (!a->itable)) { - rc = rebuild_volume(fpin, NULL, &head, a->odir_path, a->bsize, - a->hsize); - if (rc < 0) - goto err; - } - - err: - free(cur); - - if (a->analyze) { - char fname[PATH_MAX]; - FILE *fp; - - unubi_analyze(&head, first, a->odir_path); - - /* prepare output files */ - memset(fname, 0, PATH_MAX + 1); - snprintf(fname, PATH_MAX, "%s/%s", a->odir_path, FN_EH_STAT); - fp = fopen(fname, "w"); - if (fp != NULL) { - eb_chain_print(fp, head); - fclose(fp); - } - } - eb_chain_destroy(&head); - eb_chain_destroy(&first); - - return rc; -} - - -/** - * handles command line arguments, then calls unubi_volumes - **/ -int -main(int argc, char *argv[]) -{ - int rc, free_a_odir; - size_t vols_len; - uint32_t *vols; - FILE* fpin; - struct args a; - - rc = 0; - free_a_odir = 0; - vols_len = 0; - vols = NULL; - fpin = NULL; - - /* setup struct args a */ - memset(&a, 0, sizeof(a)); - a.bsize = 128 * KIB; - a.hsize = 2 * KIB; - a.vols = malloc(sizeof(*a.vols) * UBI_MAX_VOLUMES); - if (a.vols == NULL) { - ERR_MSG("out of memory\n"); - rc = ENOMEM; - goto err; - } - memset(a.vols, 0, sizeof(*a.vols) * UBI_MAX_VOLUMES); - - /* parse args and check for validity */ - parse_opt(argc, argv, &a); - if (a.img_path == NULL) { - ERR_MSG("no image file specified\n"); - rc = EINVAL; - goto err; - } - else if (a.odir_path == NULL) { - char *ptr; - int len; - - ptr = strrchr(a.img_path, '/'); - if (ptr == NULL) - ptr = a.img_path; - else - ptr++; - - len = strlen(DIR_FMT) + strlen(ptr); - free_a_odir = 1; - a.odir_path = malloc(sizeof(*a.odir_path) * len); - if (a.odir_path == NULL) { - ERR_MSG("out of memory\n"); - rc = ENOMEM; - goto err; - } - snprintf(a.odir_path, len, DIR_FMT, ptr); - } - - fpin = fopen(a.img_path, "rb"); - if (fpin == NULL) { - ERR_MSG("couldn't open file for reading: " - "%s\n", a.img_path); - rc = EINVAL; - goto err; - } - - rc = mkdir(a.odir_path, 0777); - if ((rc < 0) && (errno != EEXIST)) { - ERR_MSG("couldn't create ouput directory: " - "%s\n", a.odir_path); - rc = -rc; - goto err; - } - - /* fill in vols array */ - vols_len = count_set(a.vols, UBI_MAX_VOLUMES); - if (vols_len > 0) { - vols = malloc(sizeof(*vols) * vols_len); - if (vols == NULL) { - ERR_MSG("out of memory\n"); - rc = ENOMEM; - goto err; - } - collapse(a.vols, UBI_MAX_VOLUMES, vols, vols_len); - } - - /* unubi volumes */ - rc = unubi_volumes(fpin, vols, vols_len, &a); - if (rc < 0) { - /* ERR_MSG("error encountered while working on image file: " - "%s\n", a.img_path); */ - rc = -rc; - goto err; - } - - err: - free(a.vols); - if (free_a_odir != 0) - free(a.odir_path); - if (fpin != NULL) - fclose(fpin); - if (vols_len > 0) - free(vols); - return rc; -} diff --git a/ubi-utils/src/unubi_analyze.c b/ubi-utils/src/unubi_analyze.c deleted file mode 100644 index 3f3a480..0000000 --- a/ubi-utils/src/unubi_analyze.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006, 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Authors: Drake Dowsett, dowsett@de.ibm.com - * Contact: Andreas Arnez, arnez@de.ibm.com - * - * unubi uses the following functions to generate analysis output based on - * the header information in a raw-UBI image - */ - -/* - * TODO: use OOB data to check for eraseblock validity in NAND images - */ - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <limits.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "unubi_analyze.h" -#include "crc32.h" - -#define EC_X_INT 50 - -/** - * intcmp - function needed by qsort to order integers - **/ -int intcmp(const void *a, const void *b) -{ - int A = *(int *)a; - int B = *(int *)b; - return A - B; -} - -int longcmp(const void *a, const void *b) -{ - long long A = *(long long *)a; - long long B = *(long long *)b; - return A - B; -} - - -/** - * unubi_analyze_group_index - finds the normalized index in an array - * item: look for this item in the array - * array: array to search through - * size: length of the array - * array should be sorted for this algorithm to perform properly; - * if the item is not found returns -1, otherwise return value is the - * index in the array (note this contricts the array size to 2^32-1); - **/ -int -norm_index(uint32_t item, uint32_t *array, size_t length) -{ - size_t i, index; - - for (index = 0, i = 0; i < length; i++) { - if ((i != 0) && (array[i] != array[i - 1])) - index++; - - if (item == array[i]) - return index; - } - - return -1; -} - - -/** - * unubi_analyze_ec_hdr - generate data table and plot script - * first: head of simple linked list - * path: folder to write into - * generates a data file containing the eraseblock index in the image - * and the erase counter found in its ec header; - * if the crc check fails, the line is commented out in the data file; - * also generates a simple gnuplot sript for quickly viewing one - * display of the data file; - **/ -int -unubi_analyze_ec_hdr(struct eb_info *first, const char *path) -{ - char filename[PATH_MAX + 1]; - size_t count, eraseblocks; - uint32_t crc; - uint64_t *erase_counts; - FILE* fpdata; - FILE* fpplot; - struct eb_info *cur; - - if (first == NULL) - return -1; - - /* prepare output files */ - memset(filename, 0, PATH_MAX + 1); - snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_DATA); - fpdata = fopen(filename, "w"); - if (fpdata == NULL) - return -1; - - memset(filename, 0, PATH_MAX + 1); - snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_PLOT); - fpplot = fopen(filename, "w"); - if (fpplot == NULL) { - fclose(fpdata); - return -1; - } - - /* make executable */ - chmod(filename, 0755); - - /* first run: count elements */ - count = 0; - cur = first; - while (cur != NULL) { - cur = cur->next; - count++; - } - eraseblocks = count; - - erase_counts = malloc(eraseblocks * sizeof(*erase_counts)); - if (!erase_counts) { - perror("out of memory"); - exit(EXIT_FAILURE); - } - - memset(erase_counts, 0, eraseblocks * sizeof(*erase_counts)); - - /* second run: populate array to sort */ - count = 0; - cur = first; - while (cur != NULL) { - erase_counts[count] = __be64_to_cpu(cur->ec.ec); - cur = cur->next; - count++; - } - qsort(erase_counts, eraseblocks, sizeof(*erase_counts), - (void *)longcmp); - - /* third run: generate data file */ - count = 0; - cur = first; - fprintf(fpdata, "# eraseblock_no actual_erase_count " - "sorted_erase_count\n"); - while (cur != NULL) { - crc = 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))) - fprintf(fpdata, "# "); - - fprintf(fpdata, "%u %llu %llu", count, - __be64_to_cpu(cur->ec.ec), - erase_counts[count]); - - if (__be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) - fprintf(fpdata, " ## bad magic: %08x", - __be32_to_cpu(cur->ec.magic)); - - if (crc != __be32_to_cpu(cur->ec.hdr_crc)) - fprintf(fpdata, " ## CRC mismatch: given=%08x, " - "calc=%08x", __be32_to_cpu(cur->ec.hdr_crc), - crc); - - fprintf(fpdata, "\n"); - - cur = cur->next; - count++; - } - fclose(fpdata); - - fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n"); - fprintf(fpplot, "set xlabel \"eraseblock\"\n"); - - /* fourth run: generate plot file xtics */ - count = 0; - cur = first; - fprintf(fpplot, "set xtics ("); - while (cur != NULL) { - if ((count % EC_X_INT) == 0) { - if (count > 0) - fprintf(fpplot, ", "); - fprintf(fpplot, "%d", count); - } - - cur = cur->next; - count++; - } - fprintf(fpplot, ")\n"); - - fprintf(fpplot, "set ylabel \"erase count\"\n"); - fprintf(fpplot, "set xrange [-1:%u]\n", eraseblocks + 1); - fprintf(fpplot, "# set yrange [-1:%llu]\n", - erase_counts[eraseblocks - 1] + 1); - fprintf(fpplot, "plot \"%s\" u 1:2 t \"unsorted: %s\" with boxes\n", - FN_EH_DATA, FN_EH_DATA); - fprintf(fpplot, "# replot \"%s\" u 1:3 t \"sorted: %s\" with lines\n", - FN_EH_DATA, FN_EH_DATA); - fprintf(fpplot, "pause -1 \"press ENTER\"\n"); - - fclose(fpplot); - - return 0; -} - - -/** - * unubi_analyze_vid_hdr - generate data table and plot script - * head: head of complex linked list (eb_chain) - * path: folder to write into - * generates a data file containing the volume id, logical number, leb version, - * and data size from the vid header; - * all eraseblocks listed in the eb_chain are valid (checked in unubi); - * also generates a simple gnuplot sript for quickly viewing one - * display of the data file; - **/ -int -unubi_analyze_vid_hdr(struct eb_info **head, const char *path) -{ - char filename[PATH_MAX + 1]; - int rc, y1, y2; - size_t count, step, breadth; - uint32_t *leb_versions, *data_sizes; - FILE* fpdata; - FILE* fpplot; - struct eb_info *cur; - - if (head == NULL || *head == NULL) - return -1; - - rc = 0; - fpdata = NULL; - fpplot = NULL; - data_sizes = NULL; - leb_versions = NULL; - - /* prepare output files */ - memset(filename, 0, PATH_MAX + 1); - snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_DATA); - fpdata = fopen(filename, "w"); - if (fpdata == NULL) { - rc = -1; - goto exit; - } - - memset(filename, 0, PATH_MAX + 1); - snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_PLOT); - fpplot = fopen(filename, "w"); - if (fpplot == NULL) { - rc = -1; - goto exit; - } - - /* make executable */ - chmod(filename, 0755); - - /* first run: count elements */ - count = 0; - cur = *head; - while (cur != NULL) { - cur = cur->next; - count++; - } - breadth = count; - - leb_versions = malloc(breadth * sizeof(uint32_t)); - if (leb_versions == NULL) { - rc = -1; - goto exit; - } - memset(leb_versions, 0, breadth * sizeof(uint32_t)); - - data_sizes = malloc(breadth * sizeof(uint32_t)); - if (data_sizes == NULL) { - rc = -1; - goto exit; - } - memset(data_sizes, 0, breadth * sizeof(*data_sizes)); - - /* second run: populate arrays to sort */ - count = 0; - cur = *head; - while (cur != NULL) { - leb_versions[count] = __be32_to_cpu(cur->vid.leb_ver); - data_sizes[count] = __be32_to_cpu(cur->vid.data_size); - cur = cur->next; - count++; - } - qsort(leb_versions, breadth, sizeof(*leb_versions), (void *)intcmp); - qsort(data_sizes, breadth, sizeof(*data_sizes), (void *)intcmp); - - /* third run: generate data file */ - count = 0; - cur = *head; - fprintf(fpdata, "# x_axis vol_id lnum y1_axis leb_ver " - "y2_axis data_size\n"); - while (cur != NULL) { - y1 = norm_index(__be32_to_cpu(cur->vid.leb_ver), leb_versions, - breadth); - y2 = norm_index(__be32_to_cpu(cur->vid.data_size), data_sizes, - breadth); - - if ((y1 == -1) || (y2 == -1)) { - rc = -1; - goto exit; - } - - fprintf(fpdata, "%u %u %u %u %u %u %u\n", - count, - __be32_to_cpu(cur->vid.vol_id), - __be32_to_cpu(cur->vid.lnum), - y1, - __be32_to_cpu(cur->vid.leb_ver), - y2, - __be32_to_cpu(cur->vid.data_size)); - cur = cur->next; - count++; - } - - fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n"); - fprintf(fpplot, "set xlabel \"volume\"\n"); - - /* fourth run: generate plot file xtics */ - count = 0; - step = 0; - cur = *head; - fprintf(fpplot, "set xtics ("); - while (cur != NULL) { - if (count > 0) - fprintf(fpplot, ", "); - if (step != __be32_to_cpu(cur->vid.vol_id)) { - step = __be32_to_cpu(cur->vid.vol_id); - fprintf(fpplot, "\"%d\" %d 0", step, count); - } - else - fprintf(fpplot, "\"%d\" %d 1", - __be32_to_cpu(cur->vid.lnum), count); - cur = cur->next; - count++; - } - fprintf(fpplot, ")\n"); - fprintf(fpplot, "set nox2tics\n"); - - /* fifth run: generate plot file ytics */ - count = 0; - cur = *head; - fprintf(fpplot, "set ylabel \"leb version\"\n"); - fprintf(fpplot, "set ytics ("); - while (cur->next != NULL) { - y1 = norm_index(__be32_to_cpu(cur->vid.leb_ver), leb_versions, - breadth); - - if (y1 == -1) { - rc = -1; - goto exit; - } - - if (count > 0) - fprintf(fpplot, ", "); - - fprintf(fpplot, "\"%u\" %u", __be32_to_cpu(cur->vid.leb_ver), - y1); - - cur = cur->next; - count++; - } - fprintf(fpplot, ")\n"); - - /* sixth run: generate plot file y2tics */ - count = 0; - cur = *head; - fprintf(fpplot, "set y2label \"data size\"\n"); - fprintf(fpplot, "set y2tics ("); - while (cur != NULL) { - y2 = norm_index(__be32_to_cpu(cur->vid.data_size), - data_sizes, breadth); - - if (y2 == -1) { - rc = -1; - goto exit; - } - - if (count > 0) - fprintf(fpplot, ", "); - - fprintf(fpplot, "\"%u\" %u", __be32_to_cpu(cur->vid.data_size), - y2); - - cur = cur->next; - count++; - } - fprintf(fpplot, ")\n"); - - y1 = norm_index(leb_versions[breadth - 1], leb_versions, breadth); - y2 = norm_index(data_sizes[breadth - 1], data_sizes, breadth); - fprintf(fpplot, "set xrange [-1:%u]\n", count + 1); - fprintf(fpplot, "set yrange [-1:%u]\n", y1 + 1); - fprintf(fpplot, "set y2range [-1:%u]\n", y2 + 1); - fprintf(fpplot, "plot \"%s\" u 1:4 t \"leb version: %s\" " - "axes x1y1 with lp\n", FN_VH_DATA, FN_VH_DATA); - fprintf(fpplot, "replot \"%s\" u 1:6 t \"data size: %s\" " - "axes x1y2 with lp\n", FN_VH_DATA, FN_VH_DATA); - fprintf(fpplot, "pause -1 \"press ENTER\"\n"); - - exit: - if (fpdata != NULL) - fclose(fpdata); - if (fpplot != NULL) - fclose(fpplot); - if (data_sizes != NULL) - free(data_sizes); - if (leb_versions != NULL) - free(leb_versions); - - return rc; -} - - -/** - * unubi_analyze - run all analyses - * head: eb_chain head - * first: simple linked list of eraseblock headers (use .next) - * path: directory (without trailing slash) to output to - * returns 0 upon successful completion, or -1 otherwise - **/ -int -unubi_analyze(struct eb_info **head, struct eb_info *first, const char *path) -{ - int ec_rc, vid_rc; - - if (path == NULL) - return -1; - - ec_rc = unubi_analyze_ec_hdr(first, path); - vid_rc = unubi_analyze_vid_hdr(head, path); - if (ec_rc < 0 || vid_rc < 0) - return -1; - - return 0; -} diff --git a/ubi-utils/src/unubi_analyze.h b/ubi-utils/src/unubi_analyze.h deleted file mode 100644 index 8588219..0000000 --- a/ubi-utils/src/unubi_analyze.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006, 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __UNUBI_ANALYZE_H__ -#define __UNUBI_ANALYZE_H__ - -/* - * Author: Drake Dowsett - * Contact: Andreas Arnez (arnez@de.ibm.com) - * - * Eraseblock Chain - * - * A linked list structure to order eraseblocks by volume and logical number - * and to update by version number. Doesn't contain actual eraseblock data - * but rather the erasecounter and volume id headers as well as a position - * indicator. - * - * Diagram Example: - * - * [V1.0v0]->[V1.1v2]->[V1.2v1]->[V2.0v2]->[V2.1v0]->[V2.2v1]->NULL - * | | | | | | - * NULL [V1.1v1] [V1.2v0] [V2.0v1] NULL [V2.2v0] - * | | | | - * [V1.1v0] NULL [V2.0v0] NULL - * | | - * NULL NULL - * - * [VA.BvC] represents the eb_info for the eraseblock with the vol_id A, - * lnum B and leb_ver C - * -> represents the `next' pointer - * | represents the `older' pointer - */ - -#include <stdio.h> -#include <stdint.h> -#include <mtd/ubi-header.h> - -#define FN_EH_STAT "analysis_blocks.txt" -#define FN_EH_DATA "analysis_ec_hdr.data" -#define FN_EH_PLOT "analysis_ec_hdr.plot" -#define FN_VH_DATA "analysis_vid_hdr.data" -#define FN_VH_PLOT "analysis_vid_hdr.plot" - -struct eb_info { - struct ubi_ec_hdr ec; - struct ubi_vid_hdr vid; - - fpos_t eb_top; - uint32_t linear; - int ec_crc_ok; - int vid_crc_ok; - int data_crc_ok; - uint32_t phys_addr; - int phys_block; - - struct eb_info *next; - struct eb_info *older; -}; - -int eb_chain_insert(struct eb_info **head, struct eb_info *item); - -int eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum, - struct eb_info **pos); - -int eb_chain_print(FILE *stream, struct eb_info *head); - -int eb_chain_destroy(struct eb_info **head); - -int unubi_analyze(struct eb_info **head, struct eb_info *first, - const char *path); - -#endif /* __UNUBI_ANALYZE_H__ */ |