diff options
author | Mike Frysinger <vapier@gentoo.org> | 2011-06-25 13:20:37 -0400 |
---|---|---|
committer | Artem Bityutskiy <dedekind1@gmail.com> | 2011-06-27 09:07:07 +0300 |
commit | 3285a49dd871d54c1ec13076173ad617443baae1 (patch) | |
tree | 6b0962b6ec8437ffd54f03846f454943ea8bc443 /ubi-utils/src | |
parent | 966122b0bbb175e9d8cc9876bb455e12c1d70eb9 (diff) |
rewrite build system to avoid recursion
The ubi-utils/src/ subdir is tossed as it just complicates things for no
real gain. The dictionary.h header is relocated to the ubi-utils/include/
since other headers in there need it.
The top level clean is replaced with a `find -delete` on objects, so it
might prune more than necessary, but many projects now do this sort of
thing and no one complained there.
A "mkdep" helper generates the actual rule, and the variables are used
with "foreach" to expand these automatically.
The tests subdir is updated only to reflect the ubi-utils source move.
Otherwise, it is left untouched as making that non-recursive isn't really
worth the effort.
While we're gutting things, also through in kbuild style output while
building to make things more legible.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Artem Bityutskiy <dedekind1@gmail.com>
Diffstat (limited to 'ubi-utils/src')
-rw-r--r-- | ubi-utils/src/dictionary.c | 405 | ||||
-rw-r--r-- | ubi-utils/src/dictionary.h | 174 | ||||
-rw-r--r-- | ubi-utils/src/libiniparser.c | 646 | ||||
-rw-r--r-- | ubi-utils/src/libscan.c | 225 | ||||
-rw-r--r-- | ubi-utils/src/libubi.c | 1372 | ||||
-rw-r--r-- | ubi-utils/src/libubi_int.h | 131 | ||||
-rw-r--r-- | ubi-utils/src/libubigen.c | 315 | ||||
-rw-r--r-- | ubi-utils/src/mtdinfo.c | 446 | ||||
-rw-r--r-- | ubi-utils/src/ubiattach.c | 225 | ||||
-rw-r--r-- | ubi-utils/src/ubicrc32.c | 124 | ||||
-rw-r--r-- | ubi-utils/src/ubidetach.c | 208 | ||||
-rw-r--r-- | ubi-utils/src/ubiformat.c | 950 | ||||
-rw-r--r-- | ubi-utils/src/ubimkvol.c | 295 | ||||
-rw-r--r-- | ubi-utils/src/ubinfo.c | 434 | ||||
-rw-r--r-- | ubi-utils/src/ubinize.c | 628 | ||||
-rw-r--r-- | ubi-utils/src/ubirename.c | 147 | ||||
-rw-r--r-- | ubi-utils/src/ubirmvol.c | 211 | ||||
-rw-r--r-- | ubi-utils/src/ubirsvol.c | 245 | ||||
-rw-r--r-- | ubi-utils/src/ubiupdatevol.c | 324 | ||||
-rw-r--r-- | ubi-utils/src/ubiutils-common.c | 211 |
20 files changed, 0 insertions, 7716 deletions
diff --git a/ubi-utils/src/dictionary.c b/ubi-utils/src/dictionary.c deleted file mode 100644 index b7c9ebf..0000000 --- a/ubi-utils/src/dictionary.c +++ /dev/null @@ -1,405 +0,0 @@ -/*-------------------------------------------------------------------------*/ -/** - @file dictionary.c - @author N. Devillard - @date Sep 2007 - @version $Revision: 1.27 $ - @brief Implements a dictionary for string variables. - - This module implements a simple dictionary object, i.e. a list - of string/string associations. This object is useful to store e.g. - informations retrieved from a configuration file (ini files). -*/ -/*--------------------------------------------------------------------------*/ - -/* - $Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $ - $Revision: 1.27 $ -*/ -/*--------------------------------------------------------------------------- - Includes - ---------------------------------------------------------------------------*/ -#include "dictionary.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/** Maximum value size for integers and doubles. */ -#define MAXVALSZ 1024 - -/** Minimal allocated number of entries in a dictionary */ -#define DICTMINSZ 128 - -/** Invalid key token */ -#define DICT_INVALID_KEY ((char*)-1) - -/*--------------------------------------------------------------------------- - Private functions - ---------------------------------------------------------------------------*/ - -/* Doubles the allocated size associated to a pointer */ -/* 'size' is the current allocated size. */ -static void * mem_double(void * ptr, int size) -{ - void * newptr ; - - newptr = calloc(2*size, 1); - if (newptr==NULL) { - return NULL ; - } - memcpy(newptr, ptr, size); - free(ptr); - return newptr ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Duplicate a string - @param s String to duplicate - @return Pointer to a newly allocated string, to be freed with free() - - This is a replacement for strdup(). This implementation is provided - for systems that do not have it. - */ -/*--------------------------------------------------------------------------*/ -static char * xstrdup(char * s) -{ - char * t ; - if (!s) - return NULL ; - t = malloc(strlen(s)+1) ; - if (t) { - strcpy(t,s); - } - return t ; -} - -/*--------------------------------------------------------------------------- - Function codes - ---------------------------------------------------------------------------*/ -/*-------------------------------------------------------------------------*/ -/** - @brief Compute the hash key for a string. - @param key Character string to use for key. - @return 1 unsigned int on at least 32 bits. - - This hash function has been taken from an Article in Dr Dobbs Journal. - This is normally a collision-free function, distributing keys evenly. - The key is stored anyway in the struct so that collision can be avoided - by comparing the key itself in last resort. - */ -/*--------------------------------------------------------------------------*/ -unsigned dictionary_hash(char * key) -{ - int len ; - unsigned hash ; - int i ; - - len = strlen(key); - for (hash=0, i=0 ; i<len ; i++) { - hash += (unsigned)key[i] ; - hash += (hash<<10); - hash ^= (hash>>6) ; - } - hash += (hash <<3); - hash ^= (hash >>11); - hash += (hash <<15); - return hash ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Create a new dictionary object. - @param size Optional initial size of the dictionary. - @return 1 newly allocated dictionary objet. - - This function allocates a new dictionary object of given size and returns - it. If you do not know in advance (roughly) the number of entries in the - dictionary, give size=0. - */ -/*--------------------------------------------------------------------------*/ -dictionary * dictionary_new(int size) -{ - dictionary * d ; - - /* If no size was specified, allocate space for DICTMINSZ */ - if (size<DICTMINSZ) size=DICTMINSZ ; - - if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) { - return NULL; - } - d->size = size ; - d->val = (char **)calloc(size, sizeof(char*)); - d->key = (char **)calloc(size, sizeof(char*)); - d->hash = (unsigned int *)calloc(size, sizeof(unsigned)); - return d ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Delete a dictionary object - @param d dictionary object to deallocate. - @return void - - Deallocate a dictionary object and all memory associated to it. - */ -/*--------------------------------------------------------------------------*/ -void dictionary_del(dictionary * d) -{ - int i ; - - if (d==NULL) return ; - for (i=0 ; i<d->size ; i++) { - if (d->key[i]!=NULL) - free(d->key[i]); - if (d->val[i]!=NULL) - free(d->val[i]); - } - free(d->val); - free(d->key); - free(d->hash); - free(d); - return ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Get a value from a dictionary. - @param d dictionary object to search. - @param key Key to look for in the dictionary. - @param def Default value to return if key not found. - @return 1 pointer to internally allocated character string. - - This function locates a key in a dictionary and returns a pointer to its - value, or the passed 'def' pointer if no such key can be found in - dictionary. The returned character pointer points to data internal to the - dictionary object, you should not try to free it or modify it. - */ -/*--------------------------------------------------------------------------*/ -char * dictionary_get(dictionary * d, char * key, char * def) -{ - unsigned hash ; - int i ; - - hash = dictionary_hash(key); - for (i=0 ; i<d->size ; i++) { - if (d->key[i]==NULL) - continue ; - /* Compare hash */ - if (hash==d->hash[i]) { - /* Compare string, to avoid hash collisions */ - if (!strcmp(key, d->key[i])) { - return d->val[i] ; - } - } - } - return def ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Set a value in a dictionary. - @param d dictionary object to modify. - @param key Key to modify or add. - @param val Value to add. - @return int 0 if Ok, anything else otherwise - - If the given key is found in the dictionary, the associated value is - replaced by the provided one. If the key cannot be found in the - dictionary, it is added to it. - - It is Ok to provide a NULL value for val, but NULL values for the dictionary - or the key are considered as errors: the function will return immediately - in such a case. - - Notice that if you dictionary_set a variable to NULL, a call to - dictionary_get will return a NULL value: the variable will be found, and - its value (NULL) is returned. In other words, setting the variable - content to NULL is equivalent to deleting the variable from the - dictionary. It is not possible (in this implementation) to have a key in - the dictionary without value. - - This function returns non-zero in case of failure. - */ -/*--------------------------------------------------------------------------*/ -int dictionary_set(dictionary * d, char * key, char * val) -{ - int i ; - unsigned hash ; - - if (d==NULL || key==NULL) return -1 ; - - /* Compute hash for this key */ - hash = dictionary_hash(key) ; - /* Find if value is already in dictionary */ - if (d->n>0) { - for (i=0 ; i<d->size ; i++) { - if (d->key[i]==NULL) - continue ; - if (hash==d->hash[i]) { /* Same hash value */ - if (!strcmp(key, d->key[i])) { /* Same key */ - /* Found a value: modify and return */ - if (d->val[i]!=NULL) - free(d->val[i]); - d->val[i] = val ? xstrdup(val) : NULL ; - /* Value has been modified: return */ - return 0 ; - } - } - } - } - /* Add a new value */ - /* See if dictionary needs to grow */ - if (d->n==d->size) { - - /* Reached maximum size: reallocate dictionary */ - d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ; - d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ; - d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ; - if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) { - /* Cannot grow dictionary */ - return -1 ; - } - /* Double size */ - d->size *= 2 ; - } - - /* Insert key in the first empty slot */ - for (i=0 ; i<d->size ; i++) { - if (d->key[i]==NULL) { - /* Add key here */ - break ; - } - } - /* Copy key */ - d->key[i] = xstrdup(key); - d->val[i] = val ? xstrdup(val) : NULL ; - d->hash[i] = hash; - d->n ++ ; - return 0 ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Delete a key in a dictionary - @param d dictionary object to modify. - @param key Key to remove. - @return void - - This function deletes a key in a dictionary. Nothing is done if the - key cannot be found. - */ -/*--------------------------------------------------------------------------*/ -void dictionary_unset(dictionary * d, char * key) -{ - unsigned hash ; - int i ; - - if (key == NULL) { - return; - } - - hash = dictionary_hash(key); - for (i=0 ; i<d->size ; i++) { - if (d->key[i]==NULL) - continue ; - /* Compare hash */ - if (hash==d->hash[i]) { - /* Compare string, to avoid hash collisions */ - if (!strcmp(key, d->key[i])) { - /* Found key */ - break ; - } - } - } - if (i>=d->size) - /* Key not found */ - return ; - - free(d->key[i]); - d->key[i] = NULL ; - if (d->val[i]!=NULL) { - free(d->val[i]); - d->val[i] = NULL ; - } - d->hash[i] = 0 ; - d->n -- ; - return ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Dump a dictionary to an opened file pointer. - @param d Dictionary to dump - @param f Opened file pointer. - @return void - - Dumps a dictionary onto an opened file pointer. Key pairs are printed out - as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as - output file pointers. - */ -/*--------------------------------------------------------------------------*/ -void dictionary_dump(dictionary * d, FILE * out) -{ - int i ; - - if (d==NULL || out==NULL) return ; - if (d->n<1) { - fprintf(out, "empty dictionary\n"); - return ; - } - for (i=0 ; i<d->size ; i++) { - if (d->key[i]) { - fprintf(out, "%20s\t[%s]\n", - d->key[i], - d->val[i] ? d->val[i] : "UNDEF"); - } - } - return ; -} - - -/* Test code */ -#ifdef TESTDIC -#define NVALS 20000 -int main(int argc, char *argv[]) -{ - dictionary * d ; - char * val ; - int i ; - char cval[90] ; - - /* Allocate dictionary */ - printf("allocating...\n"); - d = dictionary_new(0); - - /* Set values in dictionary */ - printf("setting %d values...\n", NVALS); - for (i=0 ; i<NVALS ; i++) { - sprintf(cval, "%04d", i); - dictionary_set(d, cval, "salut"); - } - printf("getting %d values...\n", NVALS); - for (i=0 ; i<NVALS ; i++) { - sprintf(cval, "%04d", i); - val = dictionary_get(d, cval, DICT_INVALID_KEY); - if (val==DICT_INVALID_KEY) { - printf("cannot get value for key [%s]\n", cval); - } - } - printf("unsetting %d values...\n", NVALS); - for (i=0 ; i<NVALS ; i++) { - sprintf(cval, "%04d", i); - dictionary_unset(d, cval); - } - if (d->n != 0) { - printf("error deleting values\n"); - } - printf("deallocating...\n"); - dictionary_del(d); - return 0 ; -} -#endif -/* vim: set ts=4 et sw=4 tw=75 */ diff --git a/ubi-utils/src/dictionary.h b/ubi-utils/src/dictionary.h deleted file mode 100644 index c7d1790..0000000 --- a/ubi-utils/src/dictionary.h +++ /dev/null @@ -1,174 +0,0 @@ - -/*-------------------------------------------------------------------------*/ -/** - @file dictionary.h - @author N. Devillard - @date Sep 2007 - @version $Revision: 1.12 $ - @brief Implements a dictionary for string variables. - - This module implements a simple dictionary object, i.e. a list - of string/string associations. This object is useful to store e.g. - informations retrieved from a configuration file (ini files). -*/ -/*--------------------------------------------------------------------------*/ - -/* - $Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $ - $Author: ndevilla $ - $Date: 2007-11-23 21:37:00 $ - $Revision: 1.12 $ -*/ - -#ifndef _DICTIONARY_H_ -#define _DICTIONARY_H_ - -/*--------------------------------------------------------------------------- - Includes - ---------------------------------------------------------------------------*/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/*--------------------------------------------------------------------------- - New types - ---------------------------------------------------------------------------*/ - - -/*-------------------------------------------------------------------------*/ -/** - @brief Dictionary object - - This object contains a list of string/string associations. Each - association is identified by a unique string key. Looking up values - in the dictionary is speeded up by the use of a (hopefully collision-free) - hash function. - */ -/*-------------------------------------------------------------------------*/ -typedef struct _dictionary_ { - int n ; /** Number of entries in dictionary */ - int size ; /** Storage size */ - char ** val ; /** List of string values */ - char ** key ; /** List of string keys */ - unsigned * hash ; /** List of hash values for keys */ -} dictionary ; - - -/*--------------------------------------------------------------------------- - Function prototypes - ---------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------------*/ -/** - @brief Compute the hash key for a string. - @param key Character string to use for key. - @return 1 unsigned int on at least 32 bits. - - This hash function has been taken from an Article in Dr Dobbs Journal. - This is normally a collision-free function, distributing keys evenly. - The key is stored anyway in the struct so that collision can be avoided - by comparing the key itself in last resort. - */ -/*--------------------------------------------------------------------------*/ -unsigned dictionary_hash(char * key); - -/*-------------------------------------------------------------------------*/ -/** - @brief Create a new dictionary object. - @param size Optional initial size of the dictionary. - @return 1 newly allocated dictionary objet. - - This function allocates a new dictionary object of given size and returns - it. If you do not know in advance (roughly) the number of entries in the - dictionary, give size=0. - */ -/*--------------------------------------------------------------------------*/ -dictionary * dictionary_new(int size); - -/*-------------------------------------------------------------------------*/ -/** - @brief Delete a dictionary object - @param d dictionary object to deallocate. - @return void - - Deallocate a dictionary object and all memory associated to it. - */ -/*--------------------------------------------------------------------------*/ -void dictionary_del(dictionary * vd); - -/*-------------------------------------------------------------------------*/ -/** - @brief Get a value from a dictionary. - @param d dictionary object to search. - @param key Key to look for in the dictionary. - @param def Default value to return if key not found. - @return 1 pointer to internally allocated character string. - - This function locates a key in a dictionary and returns a pointer to its - value, or the passed 'def' pointer if no such key can be found in - dictionary. The returned character pointer points to data internal to the - dictionary object, you should not try to free it or modify it. - */ -/*--------------------------------------------------------------------------*/ -char * dictionary_get(dictionary * d, char * key, char * def); - - -/*-------------------------------------------------------------------------*/ -/** - @brief Set a value in a dictionary. - @param d dictionary object to modify. - @param key Key to modify or add. - @param val Value to add. - @return int 0 if Ok, anything else otherwise - - If the given key is found in the dictionary, the associated value is - replaced by the provided one. If the key cannot be found in the - dictionary, it is added to it. - - It is Ok to provide a NULL value for val, but NULL values for the dictionary - or the key are considered as errors: the function will return immediately - in such a case. - - Notice that if you dictionary_set a variable to NULL, a call to - dictionary_get will return a NULL value: the variable will be found, and - its value (NULL) is returned. In other words, setting the variable - content to NULL is equivalent to deleting the variable from the - dictionary. It is not possible (in this implementation) to have a key in - the dictionary without value. - - This function returns non-zero in case of failure. - */ -/*--------------------------------------------------------------------------*/ -int dictionary_set(dictionary * vd, char * key, char * val); - -/*-------------------------------------------------------------------------*/ -/** - @brief Delete a key in a dictionary - @param d dictionary object to modify. - @param key Key to remove. - @return void - - This function deletes a key in a dictionary. Nothing is done if the - key cannot be found. - */ -/*--------------------------------------------------------------------------*/ -void dictionary_unset(dictionary * d, char * key); - - -/*-------------------------------------------------------------------------*/ -/** - @brief Dump a dictionary to an opened file pointer. - @param d Dictionary to dump - @param f Opened file pointer. - @return void - - Dumps a dictionary onto an opened file pointer. Key pairs are printed out - as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as - output file pointers. - */ -/*--------------------------------------------------------------------------*/ -void dictionary_dump(dictionary * d, FILE * out); - -#endif diff --git a/ubi-utils/src/libiniparser.c b/ubi-utils/src/libiniparser.c deleted file mode 100644 index 3bea51e..0000000 --- a/ubi-utils/src/libiniparser.c +++ /dev/null @@ -1,646 +0,0 @@ - -/*-------------------------------------------------------------------------*/ -/** - @file iniparser.c - @author N. Devillard - @date Sep 2007 - @version 3.0 - @brief Parser for ini files. -*/ -/*--------------------------------------------------------------------------*/ -/* - $Id: iniparser.c,v 2.18 2008-01-03 18:35:39 ndevilla Exp $ - $Revision: 2.18 $ - $Date: 2008-01-03 18:35:39 $ -*/ -/*---------------------------- Includes ------------------------------------*/ -#include <ctype.h> -#include <libiniparser.h> - -/*---------------------------- Defines -------------------------------------*/ -#define ASCIILINESZ (1024) -#define INI_INVALID_KEY ((char*)-1) - -/*--------------------------------------------------------------------------- - Private to this module - ---------------------------------------------------------------------------*/ -/** - * This enum stores the status for each parsed line (internal use only). - */ -typedef enum _line_status_ { - LINE_UNPROCESSED, - LINE_ERROR, - LINE_EMPTY, - LINE_COMMENT, - LINE_SECTION, - LINE_VALUE -} line_status ; - -/*-------------------------------------------------------------------------*/ -/** - @brief Convert a string to lowercase. - @param s String to convert. - @return ptr to statically allocated string. - - This function returns a pointer to a statically allocated string - containing a lowercased version of the input string. Do not free - or modify the returned string! Since the returned string is statically - allocated, it will be modified at each function call (not re-entrant). - */ -/*--------------------------------------------------------------------------*/ -static char * strlwc(const char * s) -{ - static char l[ASCIILINESZ+1]; - int i ; - - if (s==NULL) return NULL ; - memset(l, 0, ASCIILINESZ+1); - i=0 ; - while (s[i] && i<ASCIILINESZ) { - l[i] = (char)tolower((int)s[i]); - i++ ; - } - l[ASCIILINESZ]=(char)0; - return l ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Remove blanks at the beginning and the end of a string. - @param s String to parse. - @return ptr to statically allocated string. - - This function returns a pointer to a statically allocated string, - which is identical to the input string, except that all blank - characters at the end and the beg. of the string have been removed. - Do not free or modify the returned string! Since the returned string - is statically allocated, it will be modified at each function call - (not re-entrant). - */ -/*--------------------------------------------------------------------------*/ -static char * strstrip(char * s) -{ - static char l[ASCIILINESZ+1]; - char * last ; - - if (s==NULL) return NULL ; - - while (isspace((int)*s) && *s) s++; - memset(l, 0, ASCIILINESZ+1); - strcpy(l, s); - last = l + strlen(l); - while (last > l) { - if (!isspace((int)*(last-1))) - break ; - last -- ; - } - *last = (char)0; - return (char*)l ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Get number of sections in a dictionary - @param d Dictionary to examine - @return int Number of sections found in dictionary - - This function returns the number of sections found in a dictionary. - The test to recognize sections is done on the string stored in the - dictionary: a section name is given as "section" whereas a key is - stored as "section:key", thus the test looks for entries that do not - contain a colon. - - This clearly fails in the case a section name contains a colon, but - this should simply be avoided. - - This function returns -1 in case of error. - */ -/*--------------------------------------------------------------------------*/ -int iniparser_getnsec(dictionary * d) -{ - int i ; - int nsec ; - - if (d==NULL) return -1 ; - nsec=0 ; - for (i=0 ; i<d->size ; i++) { - if (d->key[i]==NULL) - continue ; - if (strchr(d->key[i], ':')==NULL) { - nsec ++ ; - } - } - return nsec ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Get name for section n in a dictionary. - @param d Dictionary to examine - @param n Section number (from 0 to nsec-1). - @return Pointer to char string - - This function locates the n-th section in a dictionary and returns - its name as a pointer to a string statically allocated inside the - dictionary. Do not free or modify the returned string! - - This function returns NULL in case of error. - */ -/*--------------------------------------------------------------------------*/ -char * iniparser_getsecname(dictionary * d, int n) -{ - int i ; - int foundsec ; - - if (d==NULL || n<0) return NULL ; - foundsec=0 ; - for (i=0 ; i<d->size ; i++) { - if (d->key[i]==NULL) - continue ; - if (strchr(d->key[i], ':')==NULL) { - foundsec++ ; - if (foundsec>n) - break ; - } - } - if (foundsec<=n) { - return NULL ; - } - return d->key[i] ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Dump a dictionary to an opened file pointer. - @param d Dictionary to dump. - @param f Opened file pointer to dump to. - @return void - - This function prints out the contents of a dictionary, one element by - line, onto the provided file pointer. It is OK to specify @c stderr - or @c stdout as output files. This function is meant for debugging - purposes mostly. - */ -/*--------------------------------------------------------------------------*/ -void iniparser_dump(dictionary * d, FILE * f) -{ - int i ; - - if (d==NULL || f==NULL) return ; - for (i=0 ; i<d->size ; i++) { - if (d->key[i]==NULL) - continue ; - if (d->val[i]!=NULL) { - fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); - } else { - fprintf(f, "[%s]=UNDEF\n", d->key[i]); - } - } - return ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Save a dictionary to a loadable ini file - @param d Dictionary to dump - @param f Opened file pointer to dump to - @return void - - This function dumps a given dictionary into a loadable ini file. - It is Ok to specify @c stderr or @c stdout as output files. - */ -/*--------------------------------------------------------------------------*/ -void iniparser_dump_ini(dictionary * d, FILE * f) -{ - int i, j ; - char keym[ASCIILINESZ+1]; - int nsec ; - char * secname ; - int seclen ; - - if (d==NULL || f==NULL) return ; - - nsec = iniparser_getnsec(d); - if (nsec<1) { - /* No section in file: dump all keys as they are */ - for (i=0 ; i<d->size ; i++) { - if (d->key[i]==NULL) - continue ; - fprintf(f, "%s = %s\n", d->key[i], d->val[i]); - } - return ; - } - for (i=0 ; i<nsec ; i++) { - secname = iniparser_getsecname(d, i) ; - seclen = (int)strlen(secname); - fprintf(f, "\n[%s]\n", secname); - sprintf(keym, "%s:", secname); - for (j=0 ; j<d->size ; j++) { - if (d->key[j]==NULL) - continue ; - if (!strncmp(d->key[j], keym, seclen+1)) { - fprintf(f, - "%-30s = %s\n", - d->key[j]+seclen+1, - d->val[j] ? d->val[j] : ""); - } - } - } - fprintf(f, "\n"); - return ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Get the string associated to a key - @param d Dictionary to search - @param key Key string to look for - @param def Default value to return if key not found. - @return pointer to statically allocated character string - - This function queries a dictionary for a key. A key as read from an - ini file is given as "section:key". If the key cannot be found, - the pointer passed as 'def' is returned. - The returned char pointer is pointing to a string allocated in - the dictionary, do not free or modify it. - */ -/*--------------------------------------------------------------------------*/ -char * iniparser_getstring(dictionary * d, const char * key, char * def) -{ - char * lc_key ; - char * sval ; - - if (d==NULL || key==NULL) - return def ; - - lc_key = strlwc(key); - sval = dictionary_get(d, lc_key, def); - return sval ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Get the string associated to a key, convert to an int - @param d Dictionary to search - @param key Key string to look for - @param notfound Value to return in case of error - @return integer - - This function queries a dictionary for a key. A key as read from an - ini file is given as "section:key". If the key cannot be found, - the notfound value is returned. - - Supported values for integers include the usual C notation - so decimal, octal (starting with 0) and hexadecimal (starting with 0x) - are supported. Examples: - - "42" -> 42 - "042" -> 34 (octal -> decimal) - "0x42" -> 66 (hexa -> decimal) - - Warning: the conversion may overflow in various ways. Conversion is - totally outsourced to strtol(), see the associated man page for overflow - handling. - - Credits: Thanks to A. Becker for suggesting strtol() - */ -/*--------------------------------------------------------------------------*/ -int iniparser_getint(dictionary * d, const char * key, int notfound) -{ - char * str ; - - str = iniparser_getstring(d, key, INI_INVALID_KEY); - if (str==INI_INVALID_KEY) return notfound ; - return (int)strtol(str, NULL, 0); -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Get the string associated to a key, convert to a double - @param d Dictionary to search - @param key Key string to look for - @param notfound Value to return in case of error - @return double - - This function queries a dictionary for a key. A key as read from an - ini file is given as "section:key". If the key cannot be found, - the notfound value is returned. - */ -/*--------------------------------------------------------------------------*/ -double iniparser_getdouble(dictionary * d, char * key, double notfound) -{ - char * str ; - - str = iniparser_getstring(d, key, INI_INVALID_KEY); - if (str==INI_INVALID_KEY) return notfound ; - return atof(str); -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Get the string associated to a key, convert to a boolean - @param d Dictionary to search - @param key Key string to look for - @param notfound Value to return in case of error - @return integer - - This function queries a dictionary for a key. A key as read from an - ini file is given as "section:key". If the key cannot be found, - the notfound value is returned. - - A true boolean is found if one of the following is matched: - - - A string starting with 'y' - - A string starting with 'Y' - - A string starting with 't' - - A string starting with 'T' - - A string starting with '1' - - A false boolean is found if one of the following is matched: - - - A string starting with 'n' - - A string starting with 'N' - - A string starting with 'f' - - A string starting with 'F' - - A string starting with '0' - - The notfound value returned if no boolean is identified, does not - necessarily have to be 0 or 1. - */ -/*--------------------------------------------------------------------------*/ -int iniparser_getboolean(dictionary * d, const char * key, int notfound) -{ - char * c ; - int ret ; - - c = iniparser_getstring(d, key, INI_INVALID_KEY); - if (c==INI_INVALID_KEY) return notfound ; - if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { - ret = 1 ; - } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { - ret = 0 ; - } else { - ret = notfound ; - } - return ret; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Finds out if a given entry exists in a dictionary - @param ini Dictionary to search - @param entry Name of the entry to look for - @return integer 1 if entry exists, 0 otherwise - - Finds out if a given entry exists in the dictionary. Since sections - are stored as keys with NULL associated values, this is the only way - of querying for the presence of sections in a dictionary. - */ -/*--------------------------------------------------------------------------*/ -int iniparser_find_entry( - dictionary * ini, - char * entry -) -{ - int found=0 ; - if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { - found = 1 ; - } - return found ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Set an entry in a dictionary. - @param ini Dictionary to modify. - @param entry Entry to modify (entry name) - @param val New value to associate to the entry. - @return int 0 if Ok, -1 otherwise. - - If the given entry can be found in the dictionary, it is modified to - contain the provided value. If it cannot be found, -1 is returned. - It is Ok to set val to NULL. - */ -/*--------------------------------------------------------------------------*/ -int iniparser_set(dictionary * ini, char * entry, char * val) -{ - return dictionary_set(ini, strlwc(entry), val) ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Delete an entry in a dictionary - @param ini Dictionary to modify - @param entry Entry to delete (entry name) - @return void - - If the given entry can be found, it is deleted from the dictionary. - */ -/*--------------------------------------------------------------------------*/ -void iniparser_unset(dictionary * ini, char * entry) -{ - dictionary_unset(ini, strlwc(entry)); -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Load a single line from an INI file - @param input_line Input line, may be concatenated multi-line input - @param section Output space to store section - @param key Output space to store key - @param value Output space to store value - @return line_status value - */ -/*--------------------------------------------------------------------------*/ -static line_status iniparser_line( - char * input_line, - char * section, - char * key, - char * value) -{ - line_status sta ; - char line[ASCIILINESZ+1]; - int len ; - - strcpy(line, strstrip(input_line)); - len = (int)strlen(line); - - sta = LINE_UNPROCESSED ; - if (len<1) { - /* Empty line */ - sta = LINE_EMPTY ; - } else if (line[0]=='#') { - /* Comment line */ - sta = LINE_COMMENT ; - } else if (line[0]=='[' && line[len-1]==']') { - /* Section name */ - sscanf(line, "[%[^]]", section); - strcpy(section, strstrip(section)); - strcpy(section, strlwc(section)); - sta = LINE_SECTION ; - } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 - || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2 - || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { - /* Usual key=value, with or without comments */ - strcpy(key, strstrip(key)); - strcpy(key, strlwc(key)); - strcpy(value, strstrip(value)); - /* - * sscanf cannot handle '' or "" as empty values - * this is done here - */ - if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) { - value[0]=0 ; - } - sta = LINE_VALUE ; - } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 - || sscanf(line, "%[^=] %[=]", key, value) == 2) { - /* - * Special cases: - * key= - * key=; - * key=# - */ - strcpy(key, strstrip(key)); - strcpy(key, strlwc(key)); - value[0]=0 ; - sta = LINE_VALUE ; - } else { - /* Generate syntax error */ - sta = LINE_ERROR ; - } - return sta ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Parse an ini file and return an allocated dictionary object - @param ininame Name of the ini file to read. - @return Pointer to newly allocated dictionary - - This is the parser for ini files. This function is called, providing - the name of the file to be read. It returns a dictionary object that - should not be accessed directly, but through accessor functions - instead. - - The returned dictionary must be freed using iniparser_freedict(). - */ -/*--------------------------------------------------------------------------*/ -dictionary * iniparser_load(const char * ininame) -{ - FILE * in ; - - char line [ASCIILINESZ+1] ; - char section [ASCIILINESZ+1] ; - char key [ASCIILINESZ+1] ; - char tmp [ASCIILINESZ+1] ; - char val [ASCIILINESZ+1] ; - - int last=0 ; - int len ; - int lineno=0 ; - int errs=0; - - dictionary * dict ; - - if ((in=fopen(ininame, "r"))==NULL) { - fprintf(stderr, "iniparser: cannot open %s\n", ininame); - return NULL ; - } - - dict = dictionary_new(0) ; - if (!dict) { - fclose(in); - return NULL ; - } - - memset(line, 0, ASCIILINESZ); - memset(section, 0, ASCIILINESZ); - memset(key, 0, ASCIILINESZ); - memset(val, 0, ASCIILINESZ); - last=0 ; - - while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { - lineno++ ; - len = (int)strlen(line)-1; - /* Safety check against buffer overflows */ - if (line[len]!='\n') { - fprintf(stderr, - "iniparser: input line too long in %s (%d)\n", - ininame, - lineno); - dictionary_del(dict); - fclose(in); - return NULL ; - } - /* Get rid of \n and spaces at end of line */ - while ((len>=0) && - ((line[len]=='\n') || (isspace(line[len])))) { - line[len]=0 ; - len-- ; - } - /* Detect multi-line */ - if (line[len]=='\\') { - /* Multi-line value */ - last=len ; - continue ; - } else { - last=0 ; - } - switch (iniparser_line(line, section, key, val)) { - case LINE_EMPTY: - case LINE_COMMENT: - break ; - - case LINE_SECTION: - errs = dictionary_set(dict, section, NULL); - break ; - - case LINE_VALUE: - sprintf(tmp, "%s:%s", section, key); - errs = dictionary_set(dict, tmp, val) ; - break ; - - case LINE_ERROR: - fprintf(stderr, "iniparser: syntax error in %s (%d):\n", - ininame, - lineno); - fprintf(stderr, "-> %s\n", line); - errs++ ; - break; - - default: - break ; - } - memset(line, 0, ASCIILINESZ); - last=0; - if (errs<0) { - fprintf(stderr, "iniparser: memory allocation failure\n"); - break ; - } - } - if (errs) { - dictionary_del(dict); - dict = NULL ; - } - fclose(in); - return dict ; -} - -/*-------------------------------------------------------------------------*/ -/** - @brief Free all memory associated to an ini dictionary - @param d Dictionary to free - @return void - - Free all memory associated to an ini dictionary. - It is mandatory to call this function before the dictionary object - gets out of the current context. - */ -/*--------------------------------------------------------------------------*/ -void iniparser_freedict(dictionary * d) -{ - dictionary_del(d); -} - -/* vim: set ts=4 et sw=4 tw=75 */ diff --git a/ubi-utils/src/libscan.c b/ubi-utils/src/libscan.c deleted file mode 100644 index dc47a89..0000000 --- a/ubi-utils/src/libscan.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Artem Bityutskiy - * - * UBI scanning library. - */ - -#define PROGRAM_NAME "libscan" - -#include <sys/types.h> -#include <sys/stat.h> -#include <stdint.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> - -#include <mtd_swab.h> -#include <mtd/ubi-media.h> -#include <mtd/mtd-user.h> -#include <libmtd.h> -#include <libscan.h> -#include <crc32.h> -#include "common.h" - -static int all_ff(const void *buf, int len) -{ - int i; - const uint8_t *p = buf; - - for (i = 0; i < len; i++) - if (p[i] != 0xFF) - return 0; - return 1; -} - -int ubi_scan(struct mtd_dev_info *mtd, int fd, struct ubi_scan_info **info, - int verbose) -{ - int eb, v = (verbose == 2), pr = (verbose == 1); - struct ubi_scan_info *si; - unsigned long long sum = 0; - - si = calloc(1, sizeof(struct ubi_scan_info)); - if (!si) - return sys_errmsg("cannot allocate %zd bytes of memory", - sizeof(struct ubi_scan_info)); - - si->ec = calloc(mtd->eb_cnt, sizeof(uint32_t)); - if (!si->ec) { - sys_errmsg("cannot allocate %zd bytes of memory", - sizeof(struct ubi_scan_info)); - goto out_si; - } - - si->vid_hdr_offs = si->data_offs = -1; - - verbose(v, "start scanning eraseblocks 0-%d", mtd->eb_cnt); - for (eb = 0; eb < mtd->eb_cnt; eb++) { - int ret; - uint32_t crc; - struct ubi_ec_hdr ech; - unsigned long long ec; - - if (v) { - normsg_cont("scanning eraseblock %d", eb); - fflush(stdout); - } - if (pr) { - printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2lld %% complete ", - eb, (long long)(eb + 1) * 100 / mtd->eb_cnt); - fflush(stdout); - } - - ret = mtd_is_bad(mtd, fd, eb); - if (ret == -1) - goto out_ec; - if (ret) { - si->bad_cnt += 1; - si->ec[eb] = EB_BAD; - if (v) - printf(": bad\n"); - continue; - } - - ret = mtd_read(mtd, fd, eb, 0, &ech, sizeof(struct ubi_ec_hdr)); - if (ret < 0) - goto out_ec; - - if (be32_to_cpu(ech.magic) != UBI_EC_HDR_MAGIC) { - if (all_ff(&ech, sizeof(struct ubi_ec_hdr))) { - si->empty_cnt += 1; - si->ec[eb] = EB_EMPTY; - if (v) - printf(": empty\n"); - } else { - si->alien_cnt += 1; - si->ec[eb] = EB_ALIEN; - if (v) - printf(": alien\n"); - } - continue; - } - - crc = mtd_crc32(UBI_CRC32_INIT, &ech, UBI_EC_HDR_SIZE_CRC); - if (be32_to_cpu(ech.hdr_crc) != crc) { - si->corrupted_cnt += 1; - si->ec[eb] = EB_CORRUPTED; - if (v) - printf(": bad CRC %#08x, should be %#08x\n", - crc, be32_to_cpu(ech.hdr_crc)); - continue; - } - - ec = be64_to_cpu(ech.ec); - if (ec > EC_MAX) { - if (pr) - printf("\n"); - errmsg("erase counter in EB %d is %llu, while this " - "program expects them to be less than %u", - eb, ec, EC_MAX); - goto out_ec; - } - - if (si->vid_hdr_offs == -1) { - si->vid_hdr_offs = be32_to_cpu(ech.vid_hdr_offset); - si->data_offs = be32_to_cpu(ech.data_offset); - if (si->data_offs % mtd->min_io_size) { - if (pr) - printf("\n"); - if (v) - printf(": corrupted because of the below\n"); - warnmsg("bad data offset %d at eraseblock %d (n" - "of multiple of min. I/O unit size %d)", - si->data_offs, eb, mtd->min_io_size); - warnmsg("treat eraseblock %d as corrupted", eb); - si->corrupted_cnt += 1; - si->ec[eb] = EB_CORRUPTED; - continue; - - } - } else { - if ((int)be32_to_cpu(ech.vid_hdr_offset) != si->vid_hdr_offs) { - if (pr) - printf("\n"); - if (v) - printf(": corrupted because of the below\n"); - warnmsg("inconsistent VID header offset: was " - "%d, but is %d in eraseblock %d", - si->vid_hdr_offs, - be32_to_cpu(ech.vid_hdr_offset), eb); - warnmsg("treat eraseblock %d as corrupted", eb); - si->corrupted_cnt += 1; - si->ec[eb] = EB_CORRUPTED; - continue; - } - if ((int)be32_to_cpu(ech.data_offset) != si->data_offs) { - if (pr) - printf("\n"); - if (v) - printf(": corrupted because of the below\n"); - warnmsg("inconsistent data offset: was %d, but" - " is %d in eraseblock %d", - si->data_offs, - be32_to_cpu(ech.data_offset), eb); - warnmsg("treat eraseblock %d as corrupted", eb); - si->corrupted_cnt += 1; - si->ec[eb] = EB_CORRUPTED; - continue; - } - } - - si->ok_cnt += 1; - si->ec[eb] = ec; - if (v) - printf(": OK, erase counter %u\n", si->ec[eb]); - } - - if (si->ok_cnt != 0) { - /* Calculate mean erase counter */ - for (eb = 0; eb < mtd->eb_cnt; eb++) { - if (si->ec[eb] > EC_MAX) - continue; - sum += si->ec[eb]; - } - si->mean_ec = sum / si->ok_cnt; - } - - si->good_cnt = mtd->eb_cnt - si->bad_cnt; - verbose(v, "finished, mean EC %lld, %d OK, %d corrupted, %d empty, %d " - "alien, bad %d", si->mean_ec, si->ok_cnt, si->corrupted_cnt, - si->empty_cnt, si->alien_cnt, si->bad_cnt); - - *info = si; - if (pr) - printf("\n"); - return 0; - -out_ec: - free(si->ec); -out_si: - free(si); - *info = NULL; - return -1; -} - -void ubi_scan_free(struct ubi_scan_info *si) -{ - free(si->ec); - free(si); -} diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c deleted file mode 100644 index 4d5f316..0000000 --- a/ubi-utils/src/libubi.c +++ /dev/null @@ -1,1372 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Artem Bityutskiy - * - * UBI (Unsorted Block Images) library. - */ - -#define PROGRAM_NAME "libubi" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <dirent.h> -#include <unistd.h> -#include <limits.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <libubi.h> -#include "libubi_int.h" -#include "common.h" - -/** - * mkpath - compose full path from 2 given components. - * @path: the first component - * @name: the second component - * - * This function returns the resulting path in case of success and %NULL in - * case of failure. - */ -static char *mkpath(const char *path, const char *name) -{ - char *n; - int len1 = strlen(path); - int len2 = strlen(name); - - n = malloc(len1 + len2 + 2); - if (!n) { - sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2); - return NULL; - } - - memcpy(n, path, len1); - if (n[len1 - 1] != '/') - n[len1++] = '/'; - - memcpy(n + len1, name, len2 + 1); - return n; -} - -/** - * read_positive_ll - read a positive 'long long' value from a file. - * @file: the file to read from - * @value: the result is stored here - * - * This function reads file @file and interprets its contents as a positive - * 'long long' integer. If this is not true, it fails with %EINVAL error code. - * Returns %0 in case of success and %-1 in case of failure. - */ -static int read_positive_ll(const char *file, long long *value) -{ - int fd, rd; - char buf[50]; - - fd = open(file, O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, buf, sizeof(buf)); - if (rd == -1) { - sys_errmsg("cannot read \"%s\"", file); - goto out_error; - } - if (rd == sizeof(buf)) { - errmsg("contents of \"%s\" is too long", file); - errno = EINVAL; - goto out_error; - } - buf[rd] = '\0'; - - if (sscanf(buf, "%lld\n", value) != 1) { - errmsg("cannot read integer from \"%s\"\n", file); - errno = EINVAL; - goto out_error; - } - - if (*value < 0) { - errmsg("negative value %lld in \"%s\"", *value, file); - errno = EINVAL; - goto out_error; - } - - if (close(fd)) - return sys_errmsg("close failed on \"%s\"", file); - - return 0; - -out_error: - close(fd); - return -1; -} - -/** - * read_positive_int - read a positive 'int' value from a file. - * @file: the file to read from - * @value: the result is stored here - * - * This function is the same as 'read_positive_ll()', but it reads an 'int' - * value, not 'long long'. - */ -static int read_positive_int(const char *file, int *value) -{ - long long res; - - if (read_positive_ll(file, &res)) - return -1; - - /* Make sure the value is not too big */ - if (res > INT_MAX) { - errmsg("value %lld read from file \"%s\" is out of range", - res, file); - errno = EINVAL; - return -1; - } - - *value = res; - return 0; -} - -/** - * read_data - read data from a file. - * @file: the file to read from - * @buf: the buffer to read to - * @buf_len: buffer length - * - * This function returns number of read bytes in case of success and %-1 in - * case of failure. Note, if the file contains more then @buf_len bytes of - * date, this function fails with %EINVAL error code. - */ -static int read_data(const char *file, void *buf, int buf_len) -{ - int fd, rd, tmp, tmp1; - - fd = open(file, O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, buf, buf_len); - if (rd == -1) { - sys_errmsg("cannot read \"%s\"", file); - goto out_error; - } - - if (rd == buf_len) { - errmsg("contents of \"%s\" is too long", file); - errno = EINVAL; - goto out_error; - } - - ((char *)buf)[rd] = '\0'; - - /* Make sure all data is read */ - tmp1 = read(fd, &tmp, 1); - if (tmp1 == 1) { - sys_errmsg("cannot read \"%s\"", file); - goto out_error; - } - if (tmp1) { - errmsg("file \"%s\" contains too much data (> %d bytes)", - file, buf_len); - errno = EINVAL; - goto out_error; - } - - if (close(fd)) { - sys_errmsg("close failed on \"%s\"", file); - return -1; - } - - return rd; - -out_error: - close(fd); - return -1; -} - -/** - * read_major - read major and minor numbers from a file. - * @file: name of the file to read from - * @major: major number is returned here - * @minor: minor number is returned here - * - * This function returns % in case of succes, and %-1 in case of failure. - */ -static int read_major(const char *file, int *major, int *minor) -{ - int ret; - char buf[50]; - - ret = read_data(file, buf, 50); - if (ret < 0) - return ret; - - ret = sscanf(buf, "%d:%d\n", major, minor); - if (ret != 2) { - errno = EINVAL; - return errmsg("\"%s\" does not have major:minor format", file); - } - - if (*major < 0 || *minor < 0) { - errno = EINVAL; - return errmsg("bad major:minor %d:%d in \"%s\"", - *major, *minor, file); - } - - return 0; -} - -/** - * dev_read_int - read a positive 'int' value from an UBI device sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @value: the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int dev_read_int(const char *patt, int dev_num, int *value) -{ - char file[strlen(patt) + 50]; - - sprintf(file, patt, dev_num); - return read_positive_int(file, value); -} - -/** - * vol_read_int - read a positive 'int' value from an UBI volume sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @vol_id: volume ID - * @value: the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value) -{ - char file[strlen(patt) + 100]; - - sprintf(file, patt, dev_num, vol_id); - return read_positive_int(file, value); -} - -/** - * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @value: the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int dev_read_ll(const char *patt, int dev_num, long long *value) -{ - char file[strlen(patt) + 50]; - - sprintf(file, patt, dev_num); - return read_positive_ll(file, value); -} - -/** - * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @vol_id: volume ID - * @value: the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int vol_read_ll(const char *patt, int dev_num, int vol_id, - long long *value) -{ - char file[strlen(patt) + 100]; - - sprintf(file, patt, dev_num, vol_id); - return read_positive_ll(file, value); -} - -/** - * vol_read_data - read data from an UBI volume's sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @vol_id: volume ID - * @buf: buffer to read to - * @buf_len: buffer length - * - * This function returns number of read bytes in case of success and %-1 in - * case of failure. - */ -static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, - int buf_len) -{ - char file[strlen(patt) + 100]; - - sprintf(file, patt, dev_num, vol_id); - return read_data(file, buf, buf_len); -} - -/** - * dev_get_major - get major and minor numbers of an UBI device. - * @lib: libubi descriptor - * @dev_num: UBI device number - * @major: major number is returned here - * @minor: minor number is returned here - * - * This function returns zero in case of succes and %-1 in case of failure. - */ -static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor) -{ - char file[strlen(lib->dev_dev) + 50]; - - sprintf(file, lib->dev_dev, dev_num); - return read_major(file, major, minor); -} - -/** - * vol_get_major - get major and minor numbers of an UBI volume. - * @lib: libubi descriptor - * @dev_num: UBI device number - * @vol_id: volume ID - * @major: major number is returned here - * @minor: minor number is returned here - * - * This function returns zero in case of succes and %-1 in case of failure. - */ -static int vol_get_major(struct libubi *lib, int dev_num, int vol_id, - int *major, int *minor) -{ - char file[strlen(lib->vol_dev) + 100]; - - sprintf(file, lib->vol_dev, dev_num, vol_id); - return read_major(file, major, minor); -} - -/** - * vol_node2nums - find UBI device number and volume ID by volume device node - * file. - * @lib: UBI library descriptor - * @node: UBI character device node name - * @dev_num: UBI device number is returned here - * @vol_id: volume ID is returned hers - * - * This function returns zero in case of succes and %-1 in case of failure. - */ -static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num, - int *vol_id) -{ - struct stat st; - struct ubi_info info; - int i, fd, major, minor; - char file[strlen(lib->ubi_vol) + 100]; - - if (stat(node, &st)) - return sys_errmsg("cannot get information about \"%s\"", - node); - - if (!S_ISCHR(st.st_mode)) { - errno = EINVAL; - return errmsg("\"%s\" is not a character device", node); - } - - major = major(st.st_rdev); - minor = minor(st.st_rdev); - - if (minor == 0) { - errno = EINVAL; - return errmsg("\"%s\" is not a volume character device", node); - } - - if (ubi_get_info((libubi_t *)lib, &info)) - return -1; - - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - int major1, minor1, ret; - - ret = dev_get_major(lib, i, &major1, &minor1); - if (ret) { - if (errno == ENOENT) - continue; - return -1; - } - - if (major1 == major) - break; - } - - if (i > info.highest_dev_num) { - errno = ENODEV; - return -1; - } - - /* Make sure this UBI volume exists */ - sprintf(file, lib->ubi_vol, i, minor - 1); - fd = open(file, O_RDONLY); - if (fd == -1) { - errno = ENODEV; - return -1; - } - - *dev_num = i; - *vol_id = minor - 1; - errno = 0; - return 0; -} - -/** - * dev_node2num - find UBI device number by its character device node. - * @lib: UBI library descriptor - * @node: UBI character device node name - * @dev_num: UBI device number is returned here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int dev_node2num(struct libubi *lib, const char *node, int *dev_num) -{ - struct stat st; - struct ubi_info info; - int i, major, minor; - - if (stat(node, &st)) - return sys_errmsg("cannot get information about \"%s\"", node); - - if (!S_ISCHR(st.st_mode)) { - errno = EINVAL; - return errmsg("\"%s\" is not a character device", node); - } - - major = major(st.st_rdev); - minor = minor(st.st_rdev); - - if (minor != 0) { - errno = EINVAL; - return errmsg("\"%s\" is not an UBI character device", node); - } - - if (ubi_get_info((libubi_t *)lib, &info)) - return -1; - - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - int major1, minor1, ret; - - ret = dev_get_major(lib, i, &major1, &minor1); - if (ret) { - if (errno == ENOENT) - continue; - return -1; - } - - if (major1 == major) { - if (minor1 != 0) { - errmsg("UBI character device minor number is " - "%d, but must be 0", minor1); - errno = EINVAL; - return -1; - } - errno = 0; - *dev_num = i; - return 0; - } - } - - errno = ENODEV; - return -1; -} - -int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num) -{ - struct ubi_info info; - int i, ret, mtd_num1; - struct libubi *lib = desc; - - if (ubi_get_info(desc, &info)) - return -1; - - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1); - if (ret) { - if (errno == ENOENT) - continue; - return -1; - } - - if (mtd_num1 == mtd_num) { - errno = 0; - *dev_num = i; - return 0; - } - } - - errno = 0; - return -1; -} - -libubi_t libubi_open(void) -{ - int fd, version; - struct libubi *lib; - - lib = calloc(1, sizeof(struct libubi)); - if (!lib) - return NULL; - - lib->sysfs_ctrl = mkpath("/sys", SYSFS_CTRL); - if (!lib->sysfs_ctrl) - goto out_error; - - lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV); - if (!lib->ctrl_dev) - goto out_error; - - lib->sysfs_ubi = mkpath("/sys", SYSFS_UBI); - if (!lib->sysfs_ubi) - goto out_error; - - /* Make sure UBI is present */ - fd = open(lib->sysfs_ubi, O_RDONLY); - if (fd == -1) { - errno = 0; - goto out_error; - } - - if (close(fd)) { - sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi); - goto out_error; - } - - lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT); - if (!lib->ubi_dev) - goto out_error; - - lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER); - if (!lib->ubi_version) - goto out_error; - - lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV); - if (!lib->dev_dev) - goto out_error; - - lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS); - if (!lib->dev_avail_ebs) - goto out_error; - - lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS); - if (!lib->dev_total_ebs) - goto out_error; - - lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT); - if (!lib->dev_bad_count) - goto out_error; - - lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE); - if (!lib->dev_eb_size) - goto out_error; - - lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC); - if (!lib->dev_max_ec) - goto out_error; - - lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD); - if (!lib->dev_bad_rsvd) - goto out_error; - - lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS); - if (!lib->dev_max_vols) - goto out_error; - - lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE); - if (!lib->dev_min_io_size) - goto out_error; - - lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM); - if (!lib->dev_mtd_num) - goto out_error; - - lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT); - if (!lib->ubi_vol) - goto out_error; - - lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE); - if (!lib->vol_type) - goto out_error; - - lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV); - if (!lib->vol_dev) - goto out_error; - - lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT); - if (!lib->vol_alignment) - goto out_error; - - lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES); - if (!lib->vol_data_bytes) - goto out_error; - - lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS); - if (!lib->vol_rsvd_ebs) - goto out_error; - - lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE); - if (!lib->vol_eb_size) - goto out_error; - - lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED); - if (!lib->vol_corrupted) - goto out_error; - - lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME); - if (!lib->vol_name) - goto out_error; - - if (read_positive_int(lib->ubi_version, &version)) - goto out_error; - if (version != LIBUBI_UBI_VERSION) { - errmsg("this library was made for UBI version %d, but UBI " - "version %d is detected\n", LIBUBI_UBI_VERSION, version); - goto out_error; - } - - return lib; - -out_error: - libubi_close((libubi_t)lib); - return NULL; -} - -void libubi_close(libubi_t desc) -{ - struct libubi *lib = (struct libubi *)desc; - - free(lib->vol_name); - free(lib->vol_corrupted); - free(lib->vol_eb_size); - free(lib->vol_rsvd_ebs); - free(lib->vol_data_bytes); - free(lib->vol_alignment); - free(lib->vol_dev); - free(lib->vol_type); - free(lib->ubi_vol); - free(lib->dev_mtd_num); - free(lib->dev_min_io_size); - free(lib->dev_max_vols); - free(lib->dev_bad_rsvd); - free(lib->dev_max_ec); - free(lib->dev_eb_size); - free(lib->dev_bad_count); - free(lib->dev_total_ebs); - free(lib->dev_avail_ebs); - free(lib->dev_dev); - free(lib->ubi_version); - free(lib->ubi_dev); - free(lib->sysfs_ubi); - free(lib->ctrl_dev); - free(lib->sysfs_ctrl); - free(lib); -} - -/** - * do_attach - perform the actual attach operation. - * @node: name of the UBI control character device node - * @r: attach request - * - * This function performs the actual UBI attach operation. Returns %0 in case of - * success and %-1 in case of failure. @r->ubi_num contains newly created UBI - * device number. - */ -static int do_attach(const char *node, const struct ubi_attach_req *r) -{ - int fd, ret; - - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - - ret = ioctl(fd, UBI_IOCATT, r); - close(fd); - if (ret == -1) - return -1; - -#ifdef UDEV_SETTLE_HACK -// if (system("udevsettle") == -1) -// return -1; - usleep(100000); -#endif - return ret; -} - -int ubi_attach_mtd(libubi_t desc, const char *node, - struct ubi_attach_request *req) -{ - struct ubi_attach_req r; - int ret; - - (void)desc; - - memset(&r, 0, sizeof(struct ubi_attach_req)); - r.ubi_num = req->dev_num; - r.mtd_num = req->mtd_num; - r.vid_hdr_offset = req->vid_hdr_offset; - - ret = do_attach(node, &r); - if (ret == 0) - req->dev_num = r.ubi_num; - - return ret; -} - -#ifndef MTD_CHAR_MAJOR -/* - * This is taken from kernel <linux/mtd/mtd.h> and is unlikely to change anytime - * soon. - */ -#define MTD_CHAR_MAJOR 90 -#endif - -/** - * mtd_node_to_num - converts device node to MTD number. - * @mtd_dev_node: path to device node to convert - * - * This function converts given @mtd_dev_node to MTD device number. - * @mtd_dev_node should contain path to the MTD device node. Returns MTD device - * number in case of success and %-1 in case of failure (errno is set). - */ -static int mtd_node_to_num(const char *mtd_dev_node) -{ - int major, minor; - struct stat sb; - - if (stat(mtd_dev_node, &sb) < 0) - return sys_errmsg("cannot stat \"%s\"", mtd_dev_node); - - if (!S_ISCHR(sb.st_mode)) { - errno = EINVAL; - return sys_errmsg("\"%s\" is not a character device", - mtd_dev_node); - } - - major = major(sb.st_rdev); - minor = minor(sb.st_rdev); - - if (major != MTD_CHAR_MAJOR) { - errno = EINVAL; - return sys_errmsg("\"%s\" is not an MTD device", mtd_dev_node); - } - - return minor / 2; -} - -int ubi_attach(libubi_t desc, const char *node, struct ubi_attach_request *req) -{ - struct ubi_attach_req r; - int ret; - - if (!req->mtd_dev_node) - /* Fallback to opening by mtd_num */ - return ubi_attach_mtd(desc, node, req); - - memset(&r, 0, sizeof(struct ubi_attach_req)); - r.ubi_num = req->dev_num; - r.vid_hdr_offset = req->vid_hdr_offset; - - /* - * User has passed path to device node. Lets find out MTD device number - * of the device and pass it to the kernel. - */ - r.mtd_num = mtd_node_to_num(req->mtd_dev_node); - if (r.mtd_num == -1) - return -1; - - ret = do_attach(node, &r); - if (ret == 0) - req->dev_num = r.ubi_num; - - return ret; -} - -int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num) -{ - int ret, ubi_dev; - - ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev); - if (ret == -1) { - errno = ENODEV; - return ret; - } - - return ubi_remove_dev(desc, node, ubi_dev); -} - -int ubi_detach(libubi_t desc, const char *node, const char *mtd_dev_node) -{ - int mtd_num; - - if (!mtd_dev_node) { - errno = EINVAL; - return -1; - } - - mtd_num = mtd_node_to_num(mtd_dev_node); - if (mtd_num == -1) - return -1; - - return ubi_detach_mtd(desc, node, mtd_num); -} - -int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev) -{ - int fd, ret; - - desc = desc; - - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - ret = ioctl(fd, UBI_IOCDET, &ubi_dev); - if (ret == -1) - goto out_close; - -#ifdef UDEV_SETTLE_HACK -// if (system("udevsettle") == -1) -// return -1; - usleep(100000); -#endif - -out_close: - close(fd); - return ret; -} - -int ubi_probe_node(libubi_t desc, const char *node) -{ - struct stat st; - struct ubi_info info; - int i, fd, major, minor; - struct libubi *lib = (struct libubi *)desc; - char file[strlen(lib->ubi_vol) + 100]; - - if (stat(node, &st)) - return sys_errmsg("cannot get information about \"%s\"", node); - - if (!S_ISCHR(st.st_mode)) { - errmsg("\"%s\" is not a character device", node); - errno = EINVAL; - return -1; - } - - major = major(st.st_rdev); - minor = minor(st.st_rdev); - - if (ubi_get_info((libubi_t *)lib, &info)) - return -1; - - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - int major1, minor1, ret; - - ret = dev_get_major(lib, i, &major1, &minor1); - if (ret) { - if (errno == ENOENT) - continue; - if (!errno) - goto out_not_ubi; - return -1; - } - - if (major1 == major) - break; - } - - if (i > info.highest_dev_num) - goto out_not_ubi; - - if (minor == 0) - return 1; - - /* This is supposdely an UBI volume device node */ - sprintf(file, lib->ubi_vol, i, minor - 1); - fd = open(file, O_RDONLY); - if (fd == -1) - goto out_not_ubi; - - return 2; - -out_not_ubi: - errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to " - "any existing UBI device or volume", node, major, minor); - errno = ENODEV; - return -1; -} - -int ubi_get_info(libubi_t desc, struct ubi_info *info) -{ - DIR *sysfs_ubi; - struct dirent *dirent; - struct libubi *lib = (struct libubi *)desc; - - memset(info, 0, sizeof(struct ubi_info)); - - if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) { - /* - * Older UBI versions did not have control device, so we do not - * panic here for compatibility reasons. May be few years later - * we could return -1 here, but for now just set major:minor to - * -1. - */ - info->ctrl_major = info->ctrl_minor = -1; - } - - /* - * We have to scan the UBI sysfs directory to identify how many UBI - * devices are present. - */ - sysfs_ubi = opendir(lib->sysfs_ubi); - if (!sysfs_ubi) - return -1; - - info->lowest_dev_num = INT_MAX; - while (1) { - int dev_num, ret; - char tmp_buf[256]; - - errno = 0; - dirent = readdir(sysfs_ubi); - if (!dirent) - break; - - if (strlen(dirent->d_name) >= 255) { - errmsg("invalid entry in %s: \"%s\"", - lib->sysfs_ubi, dirent->d_name); - errno = EINVAL; - goto out_close; - } - - ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s", - &dev_num, tmp_buf); - if (ret == 1) { - info->dev_count += 1; - if (dev_num > info->highest_dev_num) - info->highest_dev_num = dev_num; - if (dev_num < info->lowest_dev_num) - info->lowest_dev_num = dev_num; - } - } - - if (!dirent && errno) { - sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); - goto out_close; - } - - if (closedir(sysfs_ubi)) - return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); - - if (info->lowest_dev_num == INT_MAX) - info->lowest_dev_num = 0; - - if (read_positive_int(lib->ubi_version, &info->version)) - return -1; - - return 0; - -out_close: - closedir(sysfs_ubi); - return -1; -} - -int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req) -{ - int fd, ret; - struct ubi_mkvol_req r; - size_t n; - - memset(&r, 0, sizeof(struct ubi_mkvol_req)); - - desc = desc; - r.vol_id = req->vol_id; - r.alignment = req->alignment; - r.bytes = req->bytes; - r.vol_type = req->vol_type; - - n = strlen(req->name); - if (n > UBI_MAX_VOLUME_NAME) - return -1; - - strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1); - r.name_len = n; - - desc = desc; - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - - ret = ioctl(fd, UBI_IOCMKVOL, &r); - if (ret == -1) { - close(fd); - return ret; - } - - close(fd); - req->vol_id = r.vol_id; - -#ifdef UDEV_SETTLE_HACK -// if (system("udevsettle") == -1) -// return -1; - usleep(100000); -#endif - - return 0; -} - -int ubi_rmvol(libubi_t desc, const char *node, int vol_id) -{ - int fd, ret; - - desc = desc; - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - - ret = ioctl(fd, UBI_IOCRMVOL, &vol_id); - if (ret == -1) { - close(fd); - return ret; - } - - close(fd); - -#ifdef UDEV_SETTLE_HACK -// if (system("udevsettle") == -1) -// return -1; - usleep(100000); -#endif - - return 0; -} - -int ubi_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol) -{ - int fd, ret; - - desc = desc; - fd = open(node, O_RDONLY); - if (fd == -1) - return -1; - - ret = ioctl(fd, UBI_IOCRNVOL, rnvol); - if (ret == -1) { - close(fd); - return ret; - } - - close(fd); - -#ifdef UDEV_SETTLE_HACK -// if (system("udevsettle") == -1) -// return -1; - usleep(100000); -#endif - - return 0; -} - -int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes) -{ - int fd, ret; - struct ubi_rsvol_req req; - - desc = desc; - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - - req.bytes = bytes; - req.vol_id = vol_id; - - ret = ioctl(fd, UBI_IOCRSVOL, &req); - close(fd); - return ret; -} - -int ubi_update_start(libubi_t desc, int fd, long long bytes) -{ - desc = desc; - if (ioctl(fd, UBI_IOCVOLUP, &bytes)) - return -1; - return 0; -} - -int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype) -{ - struct ubi_leb_change_req req; - - desc = desc; - memset(&req, 0, sizeof(struct ubi_leb_change_req)); - req.lnum = lnum; - req.bytes = bytes; - req.dtype = dtype; - - if (ioctl(fd, UBI_IOCEBCH, &req)) - return -1; - return 0; -} - -/** - * dev_present - check whether an UBI device is present. - * @lib: libubi descriptor - * @dev_num: UBI device number to check - * - * This function returns %1 if UBI device is present and %0 if not. - */ -static int dev_present(struct libubi *lib, int dev_num) -{ - struct stat st; - char file[strlen(lib->ubi_dev) + 50]; - - sprintf(file, lib->ubi_dev, dev_num); - return !stat(file, &st); -} - -int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info) -{ - DIR *sysfs_ubi; - struct dirent *dirent; - struct libubi *lib = (struct libubi *)desc; - - memset(info, 0, sizeof(struct ubi_dev_info)); - info->dev_num = dev_num; - - if (!dev_present(lib, dev_num)) - return -1; - - sysfs_ubi = opendir(lib->sysfs_ubi); - if (!sysfs_ubi) - return -1; - - info->lowest_vol_id = INT_MAX; - - while (1) { - int vol_id, ret, devno; - char tmp_buf[256]; - - errno = 0; - dirent = readdir(sysfs_ubi); - if (!dirent) - break; - - if (strlen(dirent->d_name) >= 255) { - errmsg("invalid entry in %s: \"%s\"", - lib->sysfs_ubi, dirent->d_name); - goto out_close; - } - - ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf); - if (ret == 2 && devno == dev_num) { - info->vol_count += 1; - if (vol_id > info->highest_vol_id) - info->highest_vol_id = vol_id; - if (vol_id < info->lowest_vol_id) - info->lowest_vol_id = vol_id; - } - } - - if (!dirent && errno) { - sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); - goto out_close; - } - - if (closedir(sysfs_ubi)) - return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); - - if (info->lowest_vol_id == INT_MAX) - info->lowest_vol_id = 0; - - if (dev_get_major(lib, dev_num, &info->major, &info->minor)) - return -1; - - if (dev_read_int(lib->dev_mtd_num, dev_num, &info->mtd_num)) - return -1; - if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs)) - return -1; - if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs)) - return -1; - if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count)) - return -1; - if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size)) - return -1; - if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd)) - return -1; - if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec)) - return -1; - if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count)) - return -1; - if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size)) - return -1; - - info->avail_bytes = (long long)info->avail_lebs * info->leb_size; - info->total_bytes = (long long)info->total_lebs * info->leb_size; - - return 0; - -out_close: - closedir(sysfs_ubi); - return -1; -} - -int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info) -{ - int err, dev_num; - struct libubi *lib = (struct libubi *)desc; - - err = ubi_probe_node(desc, node); - if (err != 1) { - if (err == 2) - errno = ENODEV; - return -1; - } - - if (dev_node2num(lib, node, &dev_num)) - return -1; - - return ubi_get_dev_info1(desc, dev_num, info); -} - -int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, - struct ubi_vol_info *info) -{ - int ret; - struct libubi *lib = (struct libubi *)desc; - char buf[50]; - - memset(info, 0, sizeof(struct ubi_vol_info)); - info->dev_num = dev_num; - info->vol_id = vol_id; - - if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor)) - return -1; - - ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50); - if (ret < 0) - return -1; - - if (strncmp(buf, "static\n", ret) == 0) - info->type = UBI_STATIC_VOLUME; - else if (strncmp(buf, "dynamic\n", ret) == 0) - info->type = UBI_DYNAMIC_VOLUME; - else { - errmsg("bad value at \"%s\"", buf); - errno = EINVAL; - return -1; - } - - ret = vol_read_int(lib->vol_alignment, dev_num, vol_id, - &info->alignment); - if (ret) - return -1; - ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id, - &info->data_bytes); - if (ret) - return -1; - ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs); - if (ret) - return -1; - ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size); - if (ret) - return -1; - ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id, - &info->corrupted); - if (ret) - return -1; - info->rsvd_bytes = (long long)info->leb_size * info->rsvd_lebs; - - ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name, - UBI_VOL_NAME_MAX + 2); - if (ret < 0) - return -1; - - info->name[ret - 1] = '\0'; - return 0; -} - -int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) -{ - int err, vol_id, dev_num; - struct libubi *lib = (struct libubi *)desc; - - err = ubi_probe_node(desc, node); - if (err != 2) { - if (err == 1) - errno = ENODEV; - return -1; - } - - if (vol_node2nums(lib, node, &dev_num, &vol_id)) - return -1; - - return ubi_get_vol_info1(desc, dev_num, vol_id, info); -} - -int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name, - struct ubi_vol_info *info) -{ - int i, err; - unsigned int nlen = strlen(name); - struct ubi_dev_info dev_info; - - if (nlen == 0) { - errmsg("bad \"name\" input parameter"); - errno = EINVAL; - return -1; - } - - err = ubi_get_dev_info1(desc, dev_num, &dev_info); - if (err) - return err; - - for (i = dev_info.lowest_vol_id; - i <= dev_info.highest_vol_id; i++) { - err = ubi_get_vol_info1(desc, dev_num, i, info); - if (err == -1) { - if (errno == ENOENT) - continue; - return -1; - } - - if (nlen == strlen(info->name) && !strcmp(name, info->name)) - return 0; - } - - errno = ENOENT; - return -1; -} - -int ubi_set_property(int fd, uint8_t property, uint64_t value) -{ - struct ubi_set_prop_req r; - - memset(&r, 0, sizeof(struct ubi_set_prop_req)); - r.property = property; - r.value = value; - - return ioctl(fd, UBI_IOCSETPROP, &r); -} - -int ubi_leb_unmap(int fd, int lnum) -{ - return ioctl(fd, UBI_IOCEBUNMAP, &lnum); -} - -int ubi_is_mapped(int fd, int lnum) -{ - return ioctl(fd, UBI_IOCEBISMAP, &lnum); -} diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h deleted file mode 100644 index c3aa37a..0000000 --- a/ubi-utils/src/libubi_int.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Artem Bityutskiy - * - * UBI (Unsorted Block Images) library. - */ - -#ifndef __LIBUBI_INT_H__ -#define __LIBUBI_INT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * The below are pre-define UBI file and directory names. - * - * Note, older kernels put 'ubiX_Y' directories straight to '/sys/class/ubi/'. - * New kernels puts 'ubiX_Y' directories to '/sys/class/ubi/ubiX/', which is - * saner. And for compatibility reasons it also puts symlinks to 'ubiX_Y' - * directories to '/sys/class/ubi/'. For now libubi assumes old layout. - */ - -#define SYSFS_UBI "class/ubi" -#define SYSFS_CTRL "class/misc/ubi_ctrl/" - -#define CTRL_DEV "dev" - -#define UBI_VER "version" -#define UBI_DEV_NAME_PATT "ubi%d" - -#define DEV_DEV "dev" -#define DEV_AVAIL_EBS "avail_eraseblocks" -#define DEV_TOTAL_EBS "total_eraseblocks" -#define DEV_BAD_COUNT "bad_peb_count" -#define DEV_EB_SIZE "eraseblock_size" -#define DEV_MAX_EC "max_ec" -#define DEV_MAX_RSVD "reserved_for_bad" -#define DEV_MAX_VOLS "max_vol_count" -#define DEV_MIN_IO_SIZE "min_io_size" -#define DEV_MTD_NUM "mtd_num" - -#define UBI_VOL_NAME_PATT "ubi%d_%d" -#define VOL_TYPE "type" -#define VOL_DEV "dev" -#define VOL_ALIGNMENT "alignment" -#define VOL_DATA_BYTES "data_bytes" -#define VOL_RSVD_EBS "reserved_ebs" -#define VOL_EB_SIZE "usable_eb_size" -#define VOL_CORRUPTED "corrupted" -#define VOL_NAME "name" - -/** - * libubi - UBI library description data structure. - * @sysfs: sysfs file system path - * @sysfs_ctrl: UBI control device directory in sysfs - * @ctrl_dev: UBI control device major/minor numbers sysfs file - * @sysfs_ubi: UBI directory in sysfs - * @ubi_dev: UBI device sysfs directory pattern - * @ubi_version: UBI version file sysfs path - * @dev_dev: UBI device major/minor numbers file pattern - * @dev_avail_ebs: count of available eraseblocks sysfs path pattern - * @dev_total_ebs: total eraseblocks count sysfs path pattern - * @dev_bad_count: count of bad eraseblocks sysfs path pattern - * @dev_eb_size: size of UBI device's eraseblocks sysfs path pattern - * @dev_max_ec: maximum erase counter sysfs path pattern - * @dev_bad_rsvd: count of physical eraseblock reserved for bad eraseblocks - * handling - * @dev_max_vols: maximum volumes number count sysfs path pattern - * @dev_min_io_size: minimum I/O unit size sysfs path pattern - * @dev_mtd_num: MTD device number - * @ubi_vol: UBI volume sysfs directory pattern - * @vol_type: volume type sysfs path pattern - * @vol_dev: volume major/minor numbers file pattern - * @vol_alignment: volume alignment sysfs path pattern - * @vol_data_bytes: volume data size sysfs path pattern - * @vol_rsvd_ebs: volume reserved size sysfs path pattern - * @vol_eb_size: volume eraseblock size sysfs path pattern - * @vol_corrupted: volume corruption flag sysfs path pattern - * @vol_name: volume name sysfs path pattern - */ -struct libubi -{ - char *sysfs; - char *sysfs_ctrl; - char *ctrl_dev; - char *sysfs_ubi; - char *ubi_dev; - char *ubi_version; - char *dev_dev; - char *dev_avail_ebs; - char *dev_total_ebs; - char *dev_bad_count; - char *dev_eb_size; - char *dev_max_ec; - char *dev_bad_rsvd; - char *dev_max_vols; - char *dev_min_io_size; - char *dev_mtd_num; - char *ubi_vol; - char *vol_type; - char *vol_dev; - char *vol_alignment; - char *vol_data_bytes; - char *vol_rsvd_ebs; - char *vol_eb_size; - char *vol_corrupted; - char *vol_name; - char *vol_max_count; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* !__LIBUBI_INT_H__ */ diff --git a/ubi-utils/src/libubigen.c b/ubi-utils/src/libubigen.c deleted file mode 100644 index 9eaa7f5..0000000 --- a/ubi-utils/src/libubigen.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * Copyright (C) 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Generating UBI images. - * - * Authors: Oliver Lohmann - * Artem Bityutskiy - */ - -#define PROGRAM_NAME "libubigen" - -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <string.h> - -#include <mtd/ubi-media.h> -#include <mtd_swab.h> -#include <libubigen.h> -#include <crc32.h> -#include "common.h" - -void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size, - int subpage_size, int vid_hdr_offs, int ubi_ver, - uint32_t image_seq) -{ - if (!vid_hdr_offs) { - vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1; - vid_hdr_offs /= subpage_size; - vid_hdr_offs *= subpage_size; - } - - ui->peb_size = peb_size; - ui->min_io_size = min_io_size; - ui->vid_hdr_offs = vid_hdr_offs; - ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1; - ui->data_offs /= min_io_size; - ui->data_offs *= min_io_size; - ui->leb_size = peb_size - ui->data_offs; - ui->ubi_ver = ubi_ver; - ui->image_seq = image_seq; - - ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE; - if (ui->max_volumes > UBI_MAX_VOLUMES) - ui->max_volumes = UBI_MAX_VOLUMES; - ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE; -} - -struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui) -{ - struct ubi_vtbl_record *vtbl; - int i; - - vtbl = calloc(1, ui->vtbl_size); - if (!vtbl) { - sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size); - return NULL; - } - - for (i = 0; i < ui->max_volumes; i++) { - uint32_t crc = mtd_crc32(UBI_CRC32_INIT, &vtbl[i], - UBI_VTBL_RECORD_SIZE_CRC); - vtbl[i].crc = cpu_to_be32(crc); - } - - return vtbl; -} - -int ubigen_add_volume(const struct ubigen_info *ui, - const struct ubigen_vol_info *vi, - struct ubi_vtbl_record *vtbl) -{ - struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id]; - uint32_t tmp; - - if (vi->id >= ui->max_volumes) { - errmsg("too high volume id %d, max. volumes is %d", - vi->id, ui->max_volumes); - errno = EINVAL; - return -1; - } - - if (vi->alignment >= ui->leb_size) { - errmsg("too large alignment %d, max is %d (LEB size)", - vi->alignment, ui->leb_size); - errno = EINVAL; - 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); - vtbl_rec->alignment = cpu_to_be32(vi->alignment); - vtbl_rec->vol_type = vi->type; - tmp = ui->leb_size % vi->alignment; - vtbl_rec->data_pad = cpu_to_be32(tmp); - vtbl_rec->flags = vi->flags; - - memcpy(vtbl_rec->name, vi->name, vi->name_len); - vtbl_rec->name[vi->name_len] = '\0'; - vtbl_rec->name_len = cpu_to_be16(vi->name_len); - - tmp = mtd_crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC); - vtbl_rec->crc = cpu_to_be32(tmp); - return 0; -} - -void ubigen_init_ec_hdr(const struct ubigen_info *ui, - struct ubi_ec_hdr *hdr, long long ec) -{ - uint32_t crc; - - memset(hdr, 0, sizeof(struct ubi_ec_hdr)); - - hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC); - hdr->version = ui->ubi_ver; - hdr->ec = cpu_to_be64(ec); - hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs); - hdr->data_offset = cpu_to_be32(ui->data_offs); - hdr->image_seq = cpu_to_be32(ui->image_seq); - - crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC); - hdr->hdr_crc = cpu_to_be32(crc); -} - -void ubigen_init_vid_hdr(const struct ubigen_info *ui, - const struct ubigen_vol_info *vi, - struct ubi_vid_hdr *hdr, int lnum, - const void *data, int data_size) -{ - uint32_t crc; - - memset(hdr, 0, sizeof(struct ubi_vid_hdr)); - - hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); - hdr->version = ui->ubi_ver; - hdr->vol_type = vi->type; - hdr->vol_id = cpu_to_be32(vi->id); - hdr->lnum = cpu_to_be32(lnum); - hdr->data_pad = cpu_to_be32(vi->data_pad); - hdr->compat = vi->compat; - - if (vi->type == UBI_VID_STATIC) { - hdr->data_size = cpu_to_be32(data_size); - hdr->used_ebs = cpu_to_be32(vi->used_ebs); - crc = mtd_crc32(UBI_CRC32_INIT, data, data_size); - hdr->data_crc = cpu_to_be32(crc); - } - - crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC); - hdr->hdr_crc = cpu_to_be32(crc); -} - -int ubigen_write_volume(const struct ubigen_info *ui, - const struct ubigen_vol_info *vi, long long ec, - long long bytes, int in, int out) -{ - int len = vi->usable_leb_size, rd, lnum = 0; - char *inbuf, *outbuf; - - if (vi->id >= ui->max_volumes) { - errmsg("too high volume id %d, max. volumes is %d", - vi->id, ui->max_volumes); - errno = EINVAL; - return -1; - } - - if (vi->alignment >= ui->leb_size) { - errmsg("too large alignment %d, max is %d (LEB size)", - vi->alignment, ui->leb_size); - errno = EINVAL; - return -1; - } - - inbuf = malloc(ui->leb_size); - if (!inbuf) - return sys_errmsg("cannot allocate %d bytes of memory", - ui->leb_size); - outbuf = malloc(ui->peb_size); - if (!outbuf) { - sys_errmsg("cannot allocate %d bytes of memory", ui->peb_size); - goto out_free; - } - - memset(outbuf, 0xFF, ui->data_offs); - ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec); - - while (bytes) { - int l; - struct ubi_vid_hdr *vid_hdr; - - if (bytes < len) - len = bytes; - bytes -= len; - - l = len; - do { - rd = read(in, inbuf + len - l, l); - if (rd != l) { - sys_errmsg("cannot read %d bytes from the input file", l); - goto out_free1; - } - - l -= rd; - } while (l); - - vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]); - ubigen_init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len); - - memcpy(outbuf + ui->data_offs, inbuf, len); - memset(outbuf + ui->data_offs + len, 0xFF, - ui->peb_size - ui->data_offs - len); - - if (write(out, outbuf, ui->peb_size) != ui->peb_size) { - sys_errmsg("cannot write %d bytes to the output file", ui->peb_size); - goto out_free1; - } - - lnum += 1; - } - - free(outbuf); - free(inbuf); - return 0; - -out_free1: - free(outbuf); -out_free: - free(inbuf); - return -1; -} - -int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2, - long long ec1, long long ec2, - struct ubi_vtbl_record *vtbl, int fd) -{ - int ret; - struct ubigen_vol_info vi; - char *outbuf; - struct ubi_vid_hdr *vid_hdr; - off_t seek; - - vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS; - vi.id = UBI_LAYOUT_VOLUME_ID; - vi.alignment = UBI_LAYOUT_VOLUME_ALIGN; - vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN; - vi.usable_leb_size = ui->leb_size - vi.data_pad; - vi.data_pad = ui->leb_size - vi.usable_leb_size; - vi.type = UBI_LAYOUT_VOLUME_TYPE; - vi.name = UBI_LAYOUT_VOLUME_NAME; - vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME); - vi.compat = UBI_LAYOUT_VOLUME_COMPAT; - - outbuf = malloc(ui->peb_size); - if (!outbuf) - return sys_errmsg("failed to allocate %d bytes", - ui->peb_size); - - memset(outbuf, 0xFF, ui->data_offs); - vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]); - memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size); - memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF, - ui->peb_size - ui->data_offs - ui->vtbl_size); - - seek = peb1 * ui->peb_size; - if (lseek(fd, seek, SEEK_SET) != seek) { - sys_errmsg("cannot seek output file"); - goto out_free; - } - - ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1); - ubigen_init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0); - ret = write(fd, outbuf, ui->peb_size); - if (ret != ui->peb_size) { - sys_errmsg("cannot write %d bytes", ui->peb_size); - goto out_free; - } - - seek = peb2 * ui->peb_size; - if (lseek(fd, seek, SEEK_SET) != seek) { - sys_errmsg("cannot seek output file"); - goto out_free; - } - ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2); - ubigen_init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0); - ret = write(fd, outbuf, ui->peb_size); - if (ret != ui->peb_size) { - sys_errmsg("cannot write %d bytes", ui->peb_size); - goto out_free; - } - - free(outbuf); - return 0; - -out_free: - free(outbuf); - return -1; -} diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c deleted file mode 100644 index bfd7e6d..0000000 --- a/ubi-utils/src/mtdinfo.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2009 Nokia Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * An utility to get MTD information. - * - * Author: Artem Bityutskiy - */ - -#define PROGRAM_VERSION "1.1" -#define PROGRAM_NAME "mtdinfo" - -#include <stdint.h> -#include <stdio.h> -#include <getopt.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <mtd/mtd-user.h> - -#include <libubigen.h> -#include <libmtd.h> -#include "common.h" -#include "ubiutils-common.h" - -/* The variables below are set by command line arguments */ -struct args { - int mtdn; - unsigned int all:1; - unsigned int ubinfo:1; - unsigned int map:1; - const char *node; -}; - -static struct args args = { - .mtdn = -1, - .ubinfo = 0, - .all = 0, - .node = NULL, -}; - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION - " - a tool to print MTD information."; - -static const char optionsstr[] = -"-m, --mtdn=<MTD device number> MTD device number to get information about\n" -" (deprecated option, will be removed, do not use)\n" -"-u, --ubi-info print what would UBI layout be if it was put\n" -" on this MTD device\n" -"-M, --map print eraseblock map\n" -"-a, --all print information about all MTD devices\n" -"-h, --help print help message\n" -"-V, --version print program version"; - -static const char usage[] = -"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-M] [-h] [-V] [--mtdn <MTD device number>]\n" -"\t\t[--ubi-info] [--help] [--version]\n" -"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-M] [-h] [-V] [--ubi-info] [--help]\n" -"\t\t[--version]\n" -"Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n" -"Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n" -"Example 3: " PROGRAM_NAME " /dev/mtd0 - print information MTD device /dev/mtd0\n" -"Example 4: " PROGRAM_NAME " /dev/mtd0 -u - print information MTD device /dev/mtd0\n" -"\t\t\t\tand include UBI layout information\n" -"Example 5: " PROGRAM_NAME " -a - print information about all MTD devices\n" -"\t\t\tand include UBI layout information\n"; - -static const struct option long_options[] = { - { .name = "mtdn", .has_arg = 1, .flag = NULL, .val = 'm' }, - { .name = "ubi-info", .has_arg = 0, .flag = NULL, .val = 'u' }, - { .name = "map", .has_arg = 0, .flag = NULL, .val = 'M' }, - { .name = "all", .has_arg = 0, .flag = NULL, .val = 'a' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0}, -}; - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key, error = 0; - - key = getopt_long(argc, argv, "am:uMhV", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'a': - args.all = 1; - break; - - case 'u': - args.ubinfo = 1; - break; - - case 'm': - args.mtdn = simple_strtoul(optarg, &error); - if (error || args.mtdn < 0) - return errmsg("bad MTD device number: \"%s\"", optarg); - warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6"); - break; - - case 'M': - args.map = 1; - break; - - case 'h': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - printf("%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - case ':': - return errmsg("parameter is missing"); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (optind == argc - 1) - args.node = argv[optind]; - else if (optind < argc) - return errmsg("more then one MTD device specified (use -h for help)"); - - if (args.all && (args.node || args.mtdn != -1)) { - args.mtdn = -1; - args.node = NULL; - } - - if (args.map && !args.node) - return errmsg("-M requires MTD device node name"); - - return 0; -} - -static int translate_dev(libmtd_t libmtd, const char *node) -{ - int err; - struct mtd_dev_info mtd; - - err = mtd_get_dev_info(libmtd, node, &mtd); - if (err) { - if (errno == ENODEV) - return errmsg("\"%s\" does not correspond to any " - "existing MTD device", node); - return sys_errmsg("cannot get information about MTD " - "device \"%s\"", node); - } - - args.mtdn = mtd.mtd_num; - return 0; -} - -static void print_ubi_info(const struct mtd_info *mtd_info, - const struct mtd_dev_info *mtd) -{ - struct ubigen_info ui; - - if (!mtd_info->sysfs_supported) { - errmsg("cannot provide UBI info, becasue sub-page size is " - "not known"); - return; - } - - ubigen_info_init(&ui, mtd->eb_size, mtd->min_io_size, mtd->subpage_size, - 0, 1, 0); - printf("Default UBI VID header offset: %d\n", ui.vid_hdr_offs); - printf("Default UBI data offset: %d\n", ui.data_offs); - printf("Default UBI LEB size: "); - ubiutils_print_bytes(ui.leb_size, 0); - printf("\n"); - printf("Maximum UBI volumes count: %d\n", ui.max_volumes); -} - -static void print_region_map(const struct mtd_dev_info *mtd, int fd, - const region_info_t *reginfo) -{ - unsigned long start; - int i, width; - int ret_locked, errno_locked, ret_bad, errno_bad; - - printf("Eraseblock map:\n"); - - /* Figure out the number of spaces to pad w/out libm */ - for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width) - continue; - - /* If we don't have a fd to query, just show the bare map */ - if (fd == -1) { - ret_locked = ret_bad = -1; - errno_locked = errno_bad = ENODEV; - } else - ret_locked = ret_bad = errno_locked = errno_bad = 0; - - for (i = 0; i < reginfo->numblocks; ++i) { - start = reginfo->offset + i * reginfo->erasesize; - printf(" %*i: %08lx ", width, i, start); - - if (ret_locked != -1) { - ret_locked = mtd_is_locked(mtd, fd, i); - if (ret_locked == 1) - printf("RO "); - else - errno_locked = errno; - } - if (ret_locked != 1) - printf(" "); - - if (ret_bad != -1) { - ret_bad = mtd_is_bad(mtd, fd, i); - if (ret_bad == 1) - printf("BAD "); - else - errno_bad = errno; - } - if (ret_bad != 1) - printf(" "); - - if (((i + 1) % 4) == 0) - printf("\n"); - } - if (i % 4) - printf("\n"); - - if (ret_locked == -1 && errno_locked != EOPNOTSUPP) { - errno = errno_locked; - sys_errmsg("could not read locked block info"); - } - - if (mtd->bb_allowed && ret_bad == -1 && errno_bad != EOPNOTSUPP) { - errno = errno_bad; - sys_errmsg("could not read bad block info"); - } -} - -static void print_region_info(const struct mtd_dev_info *mtd) -{ - region_info_t reginfo; - int r, fd; - - /* If we don't have any region info, just return */ - if (!args.map && mtd->region_cnt == 0) - return; - - /* First open the device so we can query it */ - fd = open(args.node, O_RDONLY | O_CLOEXEC); - if (fd == -1) { - sys_errmsg("couldn't open MTD dev: %s", args.node); - if (mtd->region_cnt) - return; - } - - /* Walk all the regions and show the map for them */ - if (mtd->region_cnt) { - for (r = 0; r < mtd->region_cnt; ++r) { - printf("Eraseblock region %i: ", r); - if (mtd_regioninfo(fd, r, ®info) == 0) { - printf(" offset: %#x size: %#x numblocks: %#x\n", - reginfo.offset, reginfo.erasesize, - reginfo.numblocks); - if (args.map) - print_region_map(mtd, fd, ®info); - } else - printf(" info is unavailable\n"); - } - } else { - reginfo.offset = 0; - reginfo.erasesize = mtd->eb_size; - reginfo.numblocks = mtd->eb_cnt; - reginfo.regionindex = 0; - print_region_map(mtd, fd, ®info); - } - - if (fd != -1) - close(fd); -} - -static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int mtdn) -{ - int err; - struct mtd_dev_info mtd; - - err = mtd_get_dev_info1(libmtd, mtdn, &mtd); - if (err) { - if (errno == ENODEV) - return errmsg("mtd%d does not correspond to any " - "existing MTD device", mtdn); - return sys_errmsg("cannot get information about MTD device %d", - mtdn); - } - - printf("mtd%d\n", mtd.mtd_num); - printf("Name: %s\n", mtd.name); - printf("Type: %s\n", mtd.type_str); - printf("Eraseblock size: "); - ubiutils_print_bytes(mtd.eb_size, 0); - printf("\n"); - printf("Amount of eraseblocks: %d (", mtd.eb_cnt); - ubiutils_print_bytes(mtd.size, 0); - printf(")\n"); - printf("Minimum input/output unit size: %d %s\n", - mtd.min_io_size, mtd.min_io_size > 1 ? "bytes" : "byte"); - if (mtd_info->sysfs_supported) - printf("Sub-page size: %d %s\n", - mtd.subpage_size, - mtd.subpage_size > 1 ? "bytes" : "byte"); - else if (mtd.type == MTD_NANDFLASH) - printf("Sub-page size: unknown\n"); - - if (mtd.oob_size > 0) - printf("OOB size: %d bytes\n", - mtd.oob_size); - if (mtd.region_cnt > 0) - printf("Additional erase regions: %d\n", mtd.oob_size); - if (mtd_info->sysfs_supported) - printf("Character device major/minor: %d:%d\n", - mtd.major, mtd.minor); - printf("Bad blocks are allowed: %s\n", - mtd.bb_allowed ? "true" : "false"); - printf("Device is writable: %s\n", - mtd.writable ? "true" : "false"); - - if (args.ubinfo) - print_ubi_info(mtd_info, &mtd); - - print_region_info(&mtd); - - printf("\n"); - return 0; -} - -static int print_general_info(libmtd_t libmtd, const struct mtd_info *mtd_info, - int all) -{ - int i, err, first = 1; - struct mtd_dev_info mtd; - - printf("Count of MTD devices: %d\n", mtd_info->mtd_dev_cnt); - if (mtd_info->mtd_dev_cnt == 0) - return 0; - - for (i = mtd_info->lowest_mtd_num; - i <= mtd_info->highest_mtd_num; i++) { - err = mtd_get_dev_info1(libmtd, i, &mtd); - if (err == -1) { - if (errno == ENODEV) - continue; - return sys_errmsg("libmtd failed get MTD device %d " - "information", i); - } - - if (!first) - printf(", mtd%d", i); - else { - printf("Present MTD devices: mtd%d", i); - first = 0; - } - } - printf("\n"); - printf("Sysfs interface supported: %s\n", - mtd_info->sysfs_supported ? "yes" : "no"); - - if (!all) - return 0; - - first = 1; - printf("\n"); - - for (i = mtd_info->lowest_mtd_num; - i <= mtd_info->highest_mtd_num; i++) { - err = print_dev_info(libmtd, mtd_info, i); - if (err) - return err; - } - - return 0; -} - -int main(int argc, char * const argv[]) -{ - int err; - libmtd_t libmtd; - struct mtd_info mtd_info; - - err = parse_opt(argc, argv); - if (err) - return -1; - - libmtd = libmtd_open(); - if (libmtd == NULL) { - if (errno == 0) - return errmsg("MTD is not present in the system"); - return sys_errmsg("cannot open libmtd"); - } - - err = mtd_get_info(libmtd, &mtd_info); - if (err) { - if (errno == ENODEV) - return errmsg("MTD is not present"); - return sys_errmsg("cannot get MTD information"); - } - - if (args.node) { - /* - * A character device was specified, translate this to MTD - * device number. - */ - err = translate_dev(libmtd, args.node); - if (err) - goto out_libmtd; - } - - if (args.mtdn == -1) - err = print_general_info(libmtd, &mtd_info, args.all); - else - err = print_dev_info(libmtd, &mtd_info, args.mtdn); - if (err) - goto out_libmtd; - - libmtd_close(libmtd); - return 0; - -out_libmtd: - libmtd_close(libmtd); - return -1; -} diff --git a/ubi-utils/src/ubiattach.c b/ubi-utils/src/ubiattach.c deleted file mode 100644 index 4f18e99..0000000 --- a/ubi-utils/src/ubiattach.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2007 Nokia Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * An utility to attach MTD devices to UBI. - * - * Author: Artem Bityutskiy - */ - -#define PROGRAM_VERSION "1.1" -#define PROGRAM_NAME "ubiattach" - -#include <stdio.h> -#include <stdint.h> -#include <getopt.h> -#include <stdlib.h> -#include <string.h> - -#include <libubi.h> -#include "common.h" -#include "ubiutils-common.h" - -#define DEFAULT_CTRL_DEV "/dev/ubi_ctrl" - -/* The variables below are set by command line arguments */ -struct args { - int devn; - int mtdn; - int vidoffs; - const char *node; - const char *dev; -}; - -static struct args args = { - .devn = UBI_DEV_NUM_AUTO, - .mtdn = -1, - .vidoffs = 0, - .node = NULL, - .dev = NULL, -}; - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION - " - a tool to attach MTD device to UBI."; - -static const char optionsstr[] = -"-d, --devn=<number> the number to assign to the newly created UBI device\n" -" (assigned automatically if this is not specified)\n" -"-p, --dev-path=<path> path to MTD device node to attach\n" -"-m, --mtdn=<number> MTD device number to attach (alternative method, e.g\n" -" if the character device node does not exist)\n" -"-O, --vid-hdr-offset VID header offset (do not specify this unless you really\n" -" know what you are doing, the default should be optimal)\n" -"-h, --help print help message\n" -"-V, --version print program version"; - -static const char usage[] = -"Usage: " PROGRAM_NAME " [<UBI control device node file name>]\n" -"\t[-m <MTD device number>] [-d <UBI device number>] [-p <path to device>]\n" -"\t[--mtdn=<MTD device number>] [--devn=<UBI device number>]\n" -"\t[--dev-path=<path to device>]\n" -"UBI control device defaults to " DEFAULT_CTRL_DEV " if not supplied.\n" -"Example 1: " PROGRAM_NAME " -p /dev/mtd0 - attach /dev/mtd0 to UBI\n" -"Example 2: " PROGRAM_NAME " -m 0 - attach MTD device 0 (mtd0) to UBI\n" -"Example 3: " PROGRAM_NAME " -m 0 -d 3 - attach MTD device 0 (mtd0) to UBI\n" -" and create UBI device number 3 (ubi3)"; - -static const struct option long_options[] = { - { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, - { .name = "dev-path", .has_arg = 1, .flag = NULL, .val = 'p' }, - { .name = "mtdn", .has_arg = 1, .flag = NULL, .val = 'm' }, - { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0}, -}; - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key, error = 0; - - key = getopt_long(argc, argv, "p:m:d:O:hV", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'p': - args.dev = optarg; - break; - case 'd': - args.devn = simple_strtoul(optarg, &error); - if (error || args.devn < 0) - return errmsg("bad UBI device number: \"%s\"", optarg); - - break; - - case 'm': - args.mtdn = simple_strtoul(optarg, &error); - if (error || args.mtdn < 0) - return errmsg("bad MTD device number: \"%s\"", optarg); - - break; - - case 'O': - args.vidoffs = simple_strtoul(optarg, &error); - if (error || args.vidoffs <= 0) - return errmsg("bad VID header offset: \"%s\"", optarg); - - break; - - case 'h': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - case ':': - return errmsg("parameter is missing"); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (optind == argc) - args.node = DEFAULT_CTRL_DEV; - else if (optind != argc - 1) - return errmsg("more then one UBI control device specified (use -h for help)"); - else - args.node = argv[optind]; - - if (args.mtdn == -1 && args.dev == NULL) - return errmsg("MTD device to attach was not specified (use -h for help)"); - - return 0; -} - -int main(int argc, char * const argv[]) -{ - int err; - libubi_t libubi; - struct ubi_info ubi_info; - struct ubi_dev_info dev_info; - struct ubi_attach_request req; - - err = parse_opt(argc, argv); - if (err) - return -1; - - libubi = libubi_open(); - if (!libubi) { - if (errno == 0) - return errmsg("UBI is not present in the system"); - return sys_errmsg("cannot open libubi"); - } - - /* - * Make sure the kernel is fresh enough and this feature is supported. - */ - err = ubi_get_info(libubi, &ubi_info); - if (err) { - sys_errmsg("cannot get UBI information"); - goto out_libubi; - } - - if (ubi_info.ctrl_major == -1) { - errmsg("MTD attach/detach feature is not supported by your kernel"); - goto out_libubi; - } - - req.dev_num = args.devn; - req.mtd_num = args.mtdn; - req.vid_hdr_offset = args.vidoffs; - req.mtd_dev_node = args.dev; - - err = ubi_attach(libubi, args.node, &req); - if (err) { - if (args.dev) - sys_errmsg("cannot attach \"%s\"", args.dev); - else - sys_errmsg("cannot attach mtd%d", args.mtdn); - goto out_libubi; - } - - /* Print some information about the new UBI device */ - err = ubi_get_dev_info1(libubi, req.dev_num, &dev_info); - if (err) { - sys_errmsg("cannot get information about newly created UBI device"); - goto out_libubi; - } - - printf("UBI device number %d, total %d LEBs (", dev_info.dev_num, dev_info.total_lebs); - ubiutils_print_bytes(dev_info.total_bytes, 0); - printf("), available %d LEBs (", dev_info.avail_lebs); - ubiutils_print_bytes(dev_info.avail_bytes, 0); - printf("), LEB size "); - ubiutils_print_bytes(dev_info.leb_size, 1); - printf("\n"); - - libubi_close(libubi); - return 0; - -out_libubi: - libubi_close(libubi); - return -1; -} diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/src/ubicrc32.c deleted file mode 100644 index 73ec595..0000000 --- a/ubi-utils/src/ubicrc32.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Calculate CRC32 with UBI start value (0xFFFFFFFF) for a given binary image. - * - * Author: Oliver Lohmann - */ - -#define PROGRAM_VERSION "1.0" -#define PROGRAM_NAME "ubicrc32" - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <getopt.h> -#include <unistd.h> -#include <mtd/ubi-media.h> -#include <crc32.h> - -#include "common.h" - -#define BUFSIZE 4096 - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION - " - a tool to calculate CRC32 with UBI start value (0xFFFFFFFF)"; - -static const char optionsstr[] = -"-h, --help print help message\n" -"-V, --version print program version"; - -static const char usage[] = -"Usage: " PROGRAM_NAME " <file to calculate CRC32 for> [-h] [--help]"; - -static const struct option long_options[] = { - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0}, -}; - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key; - - key = getopt_long(argc, argv, "hV", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'h': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - case ':': - return errmsg("parameter is missing"); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - return 0; -} - -int main(int argc, char * const argv[]) -{ - int err = 0; - uint32_t crc = UBI_CRC32_INIT; - char buf[BUFSIZE]; - FILE *fp; - - if (argc > 1) { - fp = fopen(argv[1], "r"); - if (!fp) - return sys_errmsg("cannot open \"%s\"", argv[1]); - } else - fp = stdin; - - err = parse_opt(argc, argv); - if (err) - return err; - - while (!feof(fp)) { - size_t read; - - read = fread(buf, 1, BUFSIZE, fp); - if (ferror(fp)) { - sys_errmsg("cannot read input file"); - err = -1; - goto out_close; - } - crc = mtd_crc32(crc, buf, read); - } - - printf("0x%08x\n", crc); - -out_close: - if (fp != stdin) - fclose(fp); - return err; -} diff --git a/ubi-utils/src/ubidetach.c b/ubi-utils/src/ubidetach.c deleted file mode 100644 index 668f1bd..0000000 --- a/ubi-utils/src/ubidetach.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2007 Nokia Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * An utility to delete UBI devices (detach MTD devices from UBI). - * - * Author: Artem Bityutskiy - */ - -#define PROGRAM_VERSION "1.1" -#define PROGRAM_NAME "ubidetach" - -#include <stdio.h> -#include <stdint.h> -#include <getopt.h> -#include <stdlib.h> -#include <string.h> - -#include <libubi.h> -#include "common.h" - -#define DEFAULT_CTRL_DEV "/dev/ubi_ctrl" - -/* The variables below are set by command line arguments */ -struct args { - int devn; - int mtdn; - const char *node; - const char *dev; -}; - -static struct args args = { - .devn = UBI_DEV_NUM_AUTO, - .mtdn = -1, - .node = NULL, - .dev = NULL, -}; - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION -" - tool to remove UBI devices (detach MTD devices from UBI)"; - -static const char optionsstr[] = -"-d, --devn=<UBI device number> UBI device number to delete\n" -"-p, --dev-path=<path to device> or alternatively, MTD device node path to detach\n" -"-m, --mtdn=<MTD device number> or alternatively, MTD device number to detach\n" -"-h, --help print help message\n" -"-V, --version print program version"; - -static const char usage[] = -"Usage: " PROGRAM_NAME " [<UBI control device node file name>]\n" -"\t[-d <UBI device number>] [-m <MTD device number>] [-p <path to device>]\n" -"\t[--devn=<UBI device number>] [--mtdn=<MTD device number>]\n" -"\t[--dev-path=<path to device>]\n" -"UBI control device defaults to " DEFAULT_CTRL_DEV " if not supplied.\n" -"Example 1: " PROGRAM_NAME " -p /dev/mtd0 - detach MTD device /dev/mtd0\n" -"Example 2: " PROGRAM_NAME " -d 2 - delete UBI device 2 (ubi2)\n" -"Example 3: " PROGRAM_NAME " -m 0 - detach MTD device 0 (mtd0)"; - -static const struct option long_options[] = { - { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, - { .name = "dev-path", .has_arg = 1, .flag = NULL, .val = 'p' }, - { .name = "mtdn", .has_arg = 1, .flag = NULL, .val = 'm' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0}, -}; - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key, error = 0; - - key = getopt_long(argc, argv, "p:m:d:hV", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'p': - args.dev = optarg; - break; - case 'd': - args.devn = simple_strtoul(optarg, &error); - if (error || args.devn < 0) - return errmsg("bad UBI device number: \"%s\"", optarg); - - break; - - case 'm': - args.mtdn = simple_strtoul(optarg, &error); - if (error || args.mtdn < 0) - return errmsg("bad MTD device number: \"%s\"", optarg); - - break; - - case 'h': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - case ':': - return errmsg("parameter is missing"); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (optind == argc) - args.node = DEFAULT_CTRL_DEV; - else if (optind != argc - 1) - return errmsg("more then one UBI control device specified (use -h for help)"); - else - args.node = argv[optind]; - - if (args.mtdn == -1 && args.devn == -1 && args.dev == NULL) - return errmsg("neither MTD nor UBI devices were specified (use -h for help)"); - - if (args.devn != -1) { - if (args.mtdn != -1 || args.dev != NULL) - return errmsg("specify either MTD or UBI device (use -h for help)"); - - } else if (args.mtdn != -1 && args.dev != NULL) - return errmsg("specify either MTD number or device node (use -h for help)"); - - return 0; -} - -int main(int argc, char * const argv[]) -{ - int err; - libubi_t libubi; - struct ubi_info ubi_info; - - err = parse_opt(argc, argv); - if (err) - return -1; - - libubi = libubi_open(); - if (!libubi) { - if (errno == 0) - return errmsg("UBI is not present in the system"); - return sys_errmsg("cannot open libubi"); - } - - /* - * Make sure the kernel is fresh enough and this feature is supported. - */ - err = ubi_get_info(libubi, &ubi_info); - if (err) { - sys_errmsg("cannot get UBI information"); - goto out_libubi; - } - - if (ubi_info.ctrl_major == -1) { - errmsg("MTD detach/detach feature is not supported by your kernel"); - goto out_libubi; - } - - if (args.devn != -1) { - err = ubi_remove_dev(libubi, args.node, args.devn); - if (err) { - sys_errmsg("cannot remove ubi%d", args.devn); - goto out_libubi; - } - } else { - if (args.dev != NULL) { - err = ubi_detach(libubi, args.node, args.dev); - if (err) { - sys_errmsg("cannot detach \"%s\"", args.dev); - goto out_libubi; - } - } else { - err = ubi_detach_mtd(libubi, args.node, args.mtdn); - if (err) { - sys_errmsg("cannot detach mtd%d", args.mtdn); - goto out_libubi; - } - } - } - - libubi_close(libubi); - return 0; - -out_libubi: - libubi_close(libubi); - return -1; -} - diff --git a/ubi-utils/src/ubiformat.c b/ubi-utils/src/ubiformat.c deleted file mode 100644 index c4b944a..0000000 --- a/ubi-utils/src/ubiformat.c +++ /dev/null @@ -1,950 +0,0 @@ -/* - * Copyright (C) 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * An utility to format MTD devices into UBI and flash UBI images. - * - * Author: Artem Bityutskiy - */ - -/* - * Maximum amount of consequtive eraseblocks which are considered as normal by - * this utility. Otherwise it is assume that something is wrong with the flash - * or the driver, and eraseblocks are stopped being marked as bad. - */ -#define MAX_CONSECUTIVE_BAD_BLOCKS 4 - -#define PROGRAM_VERSION "1.5" -#define PROGRAM_NAME "ubiformat" - -#include <sys/stat.h> -#include <unistd.h> -#include <stdint.h> -#include <stdlib.h> -#include <getopt.h> -#include <fcntl.h> - -#include <libubi.h> -#include <libmtd.h> -#include <libscan.h> -#include <libubigen.h> -#include <mtd_swab.h> -#include <crc32.h> -#include "common.h" -#include "ubiutils-common.h" - -/* The variables below are set by command line arguments */ -struct args { - unsigned int yes:1; - unsigned int quiet:1; - unsigned int verbose:1; - unsigned int override_ec:1; - unsigned int novtbl:1; - unsigned int manual_subpage; - int subpage_size; - int vid_hdr_offs; - int ubi_ver; - uint32_t image_seq; - off_t image_sz; - long long ec; - const char *image; - const char *node; - int node_fd; -}; - -static struct args args = -{ - .ubi_ver = 1, -}; - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION - " - a tool to format MTD devices and flash UBI images"; - -static const char optionsstr[] = -"-s, --sub-page-size=<bytes> minimum input/output unit used for UBI\n" -" headers, e.g. sub-page size in case of NAND\n" -" flash (equivalent to the minimum input/output\n" -" unit size by default)\n" -"-O, --vid-hdr-offset=<offs> offset if the VID header from start of the\n" -" physical eraseblock (default is the next\n" -" minimum I/O unit or sub-page after the EC\n" -" header)\n" -"-n, --no-volume-table only erase all eraseblock and preserve erase\n" -" counters, do not write empty volume table\n" -"-f, --flash-image=<file> flash image file, or '-' for stdin\n" -"-S, --image-size=<bytes> bytes in input, if not reading from file\n" -"-e, --erase-counter=<value> use <value> as the erase counter value for all\n" -" eraseblocks\n" -"-x, --ubi-ver=<num> UBI version number to put to EC headers\n" -" (default is 1)\n" -"-Q, --image-seq=<num> 32-bit UBI image sequence number to use\n" -" (by default a random number is picked)\n" -"-y, --yes assume the answer is \"yes\" for all question\n" -" this program would otherwise ask\n" -"-q, --quiet suppress progress percentage information\n" -"-v, --verbose be verbose\n" -"-h, -?, --help print help message\n" -"-V, --version print program version\n"; - -static const char usage[] = -"Usage: " PROGRAM_NAME " <MTD device node file name> [-s <bytes>] [-O <offs>] [-n]\n" -"\t\t\t[-f <file>] [-S <bytes>] [-e <value>] [-x <num>] [-y] [-q] [-v] [-h] [-v]\n" -"\t\t\t[--sub-page-size=<bytes>] [--vid-hdr-offset=<offs>] [--no-volume-table]\n" -"\t\t\t[--flash-image=<file>] [--image-size=<bytes>] [--erase-counter=<value>]\n" -"\t\t\t[--ubi-ver=<num>] [--yes] [--quiet] [--verbose] [--help] [--version]\n\n" -"Example 1: " PROGRAM_NAME " /dev/mtd0 -y - format MTD device number 0 and do\n" -" not ask questions.\n" -"Example 2: " PROGRAM_NAME " /dev/mtd0 -q -e 0 - format MTD device number 0,\n" -" be quiet and force erase counter value 0."; - -static const struct option long_options[] = { - { .name = "sub-page-size", .has_arg = 1, .flag = NULL, .val = 's' }, - { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' }, - { .name = "no-volume-table", .has_arg = 0, .flag = NULL, .val = 'n' }, - { .name = "flash-image", .has_arg = 1, .flag = NULL, .val = 'f' }, - { .name = "image-size", .has_arg = 1, .flag = NULL, .val = 'S' }, - { .name = "yes", .has_arg = 0, .flag = NULL, .val = 'y' }, - { .name = "erase-counter", .has_arg = 1, .flag = NULL, .val = 'e' }, - { .name = "quiet", .has_arg = 0, .flag = NULL, .val = 'q' }, - { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, - { .name = "ubi-ver", .has_arg = 1, .flag = NULL, .val = 'x' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0}, -}; - -static int parse_opt(int argc, char * const argv[]) -{ - ubiutils_srand(); - args.image_seq = rand(); - - while (1) { - int key, error = 0; - unsigned long int image_seq; - - key = getopt_long(argc, argv, "nh?Vyqve:x:s:O:f:S:", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 's': - args.subpage_size = ubiutils_get_bytes(optarg); - if (args.subpage_size <= 0) - return errmsg("bad sub-page size: \"%s\"", optarg); - if (!is_power_of_2(args.subpage_size)) - return errmsg("sub-page size should be power of 2"); - break; - - case 'O': - args.vid_hdr_offs = simple_strtoul(optarg, &error); - if (error || args.vid_hdr_offs <= 0) - return errmsg("bad VID header offset: \"%s\"", optarg); - break; - - case 'e': - args.ec = simple_strtoull(optarg, &error); - if (error || args.ec < 0) - return errmsg("bad erase counter value: \"%s\"", optarg); - if (args.ec >= EC_MAX) - return errmsg("too high erase %llu, counter, max is %u", args.ec, EC_MAX); - args.override_ec = 1; - break; - - case 'f': - args.image = optarg; - break; - - case 'S': - args.image_sz = ubiutils_get_bytes(optarg); - if (args.image_sz <= 0) - return errmsg("bad image-size: \"%s\"", optarg); - break; - - case 'n': - args.novtbl = 1; - break; - - case 'y': - args.yes = 1; - break; - - case 'q': - args.quiet = 1; - break; - - case 'x': - args.ubi_ver = simple_strtoul(optarg, &error); - if (error || args.ubi_ver < 0) - return errmsg("bad UBI version: \"%s\"", optarg); - break; - - case 'Q': - image_seq = simple_strtoul(optarg, &error); - if (error || image_seq > 0xFFFFFFFF) - return errmsg("bad UBI image sequence number: \"%s\"", optarg); - args.image_seq = image_seq; - break; - - - case 'v': - args.verbose = 1; - break; - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - case 'h': - case '?': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case ':': - return errmsg("parameter is missing"); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (args.quiet && args.verbose) - return errmsg("using \"-q\" and \"-v\" at the same time does not make sense"); - - if (optind == argc) - return errmsg("MTD device name was not specified (use -h for help)"); - else if (optind != argc - 1) - return errmsg("more then one MTD device specified (use -h for help)"); - - if (args.image && args.novtbl) - return errmsg("-n cannot be used together with -f"); - - - args.node = argv[optind]; - return 0; -} - -static int want_exit(void) -{ - char buf[4]; - - while (1) { - normsg_cont("continue? (yes/no) "); - if (scanf("%3s", buf) == EOF) { - sys_errmsg("scanf returned unexpected EOF, assume \"yes\""); - return 1; - } - if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1)) - return 0; - if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1)) - return 1; - } -} - -static int answer_is_yes(void) -{ - char buf[4]; - - while (1) { - if (scanf("%3s", buf) == EOF) { - sys_errmsg("scanf returned unexpected EOF, assume \"no\""); - return 0; - } - if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1)) - return 1; - if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1)) - return 0; - } -} - -static void print_bad_eraseblocks(const struct mtd_dev_info *mtd, - const struct ubi_scan_info *si) -{ - int first = 1, eb; - - if (si->bad_cnt == 0) - return; - - normsg_cont("%d bad eraseblocks found, numbers: ", si->bad_cnt); - for (eb = 0; eb < mtd->eb_cnt; eb++) { - if (si->ec[eb] != EB_BAD) - continue; - if (first) { - printf("%d", eb); - first = 0; - } else - printf(", %d", eb); - } - printf("\n"); -} - -static int change_ech(struct ubi_ec_hdr *hdr, uint32_t image_seq, - long long ec) -{ - uint32_t crc; - - /* Check the EC header */ - if (be32_to_cpu(hdr->magic) != UBI_EC_HDR_MAGIC) - return errmsg("bad UBI magic %#08x, should be %#08x", - be32_to_cpu(hdr->magic), UBI_EC_HDR_MAGIC); - - crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC); - if (be32_to_cpu(hdr->hdr_crc) != crc) - return errmsg("bad CRC %#08x, should be %#08x\n", - crc, be32_to_cpu(hdr->hdr_crc)); - - hdr->image_seq = cpu_to_be32(image_seq); - hdr->ec = cpu_to_be64(ec); - crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC); - hdr->hdr_crc = cpu_to_be32(crc); - - return 0; -} - -static int drop_ffs(const struct mtd_dev_info *mtd, const void *buf, int len) -{ - int i; - - for (i = len - 1; i >= 0; i--) - if (((const uint8_t *)buf)[i] != 0xFF) - break; - - /* The resulting length must be aligned to the minimum flash I/O size */ - len = i + 1; - len = (len + mtd->min_io_size - 1) / mtd->min_io_size; - len *= mtd->min_io_size; - return len; -} - -static int open_file(off_t *sz) -{ - int fd; - - if (!strcmp(args.image, "-")) { - if (args.image_sz == 0) - return errmsg("must use '-S' with non-zero value when reading from stdin"); - - *sz = args.image_sz; - fd = dup(STDIN_FILENO); - if (fd < 0) - return sys_errmsg("failed to dup stdin"); - } else { - struct stat st; - - if (stat(args.image, &st)) - return sys_errmsg("cannot open \"%s\"", args.image); - - *sz = st.st_size; - fd = open(args.image, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", args.image); - } - - return fd; -} - -static int read_all(int fd, void *buf, size_t len) -{ - while (len > 0) { - ssize_t l = read(fd, buf, len); - if (l == 0) - return errmsg("eof reached; %zu bytes remaining", len); - else if (l > 0) { - buf += l; - len -= l; - } else if (errno == EINTR || errno == EAGAIN) - continue; - else - return sys_errmsg("reading failed; %zu bytes remaining", len); - } - - return 0; -} - -/* - * Returns %-1 if consecutive bad blocks exceeds the - * MAX_CONSECUTIVE_BAD_BLOCKS and returns %0 otherwise. - */ -static int consecutive_bad_check(int eb) -{ - static int consecutive_bad_blocks = 1; - static int prev_bb = -1; - - if (prev_bb == -1) - prev_bb = eb; - - if (eb == prev_bb + 1) - consecutive_bad_blocks += 1; - else - consecutive_bad_blocks = 1; - - prev_bb = eb; - - if (consecutive_bad_blocks >= MAX_CONSECUTIVE_BAD_BLOCKS) { - if (!args.quiet) - printf("\n"); - return errmsg("consecutive bad blocks exceed limit: %d, bad flash?", - MAX_CONSECUTIVE_BAD_BLOCKS); - } - - return 0; -} - -/* TODO: we should actually torture the PEB before marking it as bad */ -static int mark_bad(const struct mtd_dev_info *mtd, struct ubi_scan_info *si, int eb) -{ - int err; - - if (!args.yes) { - normsg_cont("mark it as bad? Continue (yes/no) "); - if (!answer_is_yes()) - return -1; - } - - if (!args.quiet) - normsg_cont("marking block %d bad", eb); - - if (!args.quiet) - printf("\n"); - - if (!mtd->bb_allowed) { - if (!args.quiet) - printf("\n"); - return errmsg("bad blocks not supported by this flash"); - } - - err = mtd_mark_bad(mtd, args.node_fd, eb); - if (err) - return err; - - si->bad_cnt += 1; - si->ec[eb] = EB_BAD; - - return consecutive_bad_check(eb); -} - -static int flash_image(libmtd_t libmtd, const struct mtd_dev_info *mtd, - const struct ubigen_info *ui, struct ubi_scan_info *si) -{ - int fd, img_ebs, eb, written_ebs = 0, divisor; - off_t st_size; - - fd = open_file(&st_size); - if (fd < 0) - return fd; - - img_ebs = st_size / mtd->eb_size; - - if (img_ebs > si->good_cnt) { - sys_errmsg("file \"%s\" is too large (%lld bytes)", - args.image, (long long)st_size); - goto out_close; - } - - if (st_size % mtd->eb_size) { - return sys_errmsg("file \"%s\" (size %lld bytes) is not multiple of ""eraseblock size (%d bytes)", - args.image, (long long)st_size, mtd->eb_size); - goto out_close; - } - - verbose(args.verbose, "will write %d eraseblocks", img_ebs); - divisor = img_ebs; - for (eb = 0; eb < mtd->eb_cnt; eb++) { - int err, new_len; - char buf[mtd->eb_size]; - long long ec; - - if (!args.quiet && !args.verbose) { - printf("\r" PROGRAM_NAME ": flashing eraseblock %d -- %2lld %% complete ", - eb, (long long)(eb + 1) * 100 / divisor); - fflush(stdout); - } - - if (si->ec[eb] == EB_BAD) { - divisor += 1; - continue; - } - - if (args.verbose) { - normsg_cont("eraseblock %d: erase", eb); - fflush(stdout); - } - - err = mtd_erase(libmtd, mtd, args.node_fd, eb); - if (err) { - if (!args.quiet) - printf("\n"); - sys_errmsg("failed to erase eraseblock %d", eb); - - if (errno != EIO) - goto out_close; - - if (mark_bad(mtd, si, eb)) - goto out_close; - - continue; - } - - err = read_all(fd, buf, mtd->eb_size); - if (err) { - sys_errmsg("failed to read eraseblock %d from \"%s\"", - written_ebs, args.image); - goto out_close; - } - - if (args.override_ec) - ec = args.ec; - else if (si->ec[eb] <= EC_MAX) - ec = si->ec[eb] + 1; - else - ec = si->mean_ec; - - if (args.verbose) { - printf(", change EC to %lld", ec); - fflush(stdout); - } - - err = change_ech((struct ubi_ec_hdr *)buf, ui->image_seq, ec); - if (err) { - errmsg("bad EC header at eraseblock %d of \"%s\"", - written_ebs, args.image); - goto out_close; - } - - if (args.verbose) { - printf(", write data\n"); - fflush(stdout); - } - - new_len = drop_ffs(mtd, buf, mtd->eb_size); - - err = mtd_write(mtd, args.node_fd, eb, 0, buf, new_len); - if (err) { - sys_errmsg("cannot write eraseblock %d", eb); - - if (errno != EIO) - goto out_close; - - err = mtd_torture(libmtd, mtd, args.node_fd, eb); - if (err) { - if (mark_bad(mtd, si, eb)) - goto out_close; - } - continue; - } - if (++written_ebs >= img_ebs) - break; - } - - if (!args.quiet && !args.verbose) - printf("\n"); - close(fd); - return eb + 1; - -out_close: - close(fd); - return -1; -} - -static int format(libmtd_t libmtd, const struct mtd_dev_info *mtd, - const struct ubigen_info *ui, struct ubi_scan_info *si, - int start_eb, int novtbl) -{ - int eb, err, write_size; - struct ubi_ec_hdr *hdr; - struct ubi_vtbl_record *vtbl; - int eb1 = -1, eb2 = -1; - long long ec1 = -1, ec2 = -1; - - write_size = UBI_EC_HDR_SIZE + mtd->subpage_size - 1; - write_size /= mtd->subpage_size; - write_size *= mtd->subpage_size; - hdr = malloc(write_size); - if (!hdr) - return sys_errmsg("cannot allocate %d bytes of memory", write_size); - memset(hdr, 0xFF, write_size); - - for (eb = start_eb; eb < mtd->eb_cnt; eb++) { - long long ec; - - if (!args.quiet && !args.verbose) { - printf("\r" PROGRAM_NAME ": formatting eraseblock %d -- %2lld %% complete ", - eb, (long long)(eb + 1 - start_eb) * 100 / (mtd->eb_cnt - start_eb)); - fflush(stdout); - } - - if (si->ec[eb] == EB_BAD) - continue; - - if (args.override_ec) - ec = args.ec; - else if (si->ec[eb] <= EC_MAX) - ec = si->ec[eb] + 1; - else - ec = si->mean_ec; - ubigen_init_ec_hdr(ui, hdr, ec); - - if (args.verbose) { - normsg_cont("eraseblock %d: erase", eb); - fflush(stdout); - } - - err = mtd_erase(libmtd, mtd, args.node_fd, eb); - if (err) { - if (!args.quiet) - printf("\n"); - - sys_errmsg("failed to erase eraseblock %d", eb); - if (errno != EIO) - goto out_free; - - if (mark_bad(mtd, si, eb)) - goto out_free; - continue; - } - - if ((eb1 == -1 || eb2 == -1) && !novtbl) { - if (eb1 == -1) { - eb1 = eb; - ec1 = ec; - } else if (eb2 == -1) { - eb2 = eb; - ec2 = ec; - } - if (args.verbose) - printf(", do not write EC, leave for vtbl\n"); - continue; - } - - if (args.verbose) { - printf(", write EC %lld\n", ec); - fflush(stdout); - } - - err = mtd_write(mtd, args.node_fd, eb, 0, hdr, write_size); - if (err) { - if (!args.quiet && !args.verbose) - printf("\n"); - sys_errmsg("cannot write EC header (%d bytes buffer) to eraseblock %d", - write_size, eb); - - if (errno != EIO) { - if (!args.subpage_size != mtd->min_io_size) - normsg("may be sub-page size is " - "incorrect?"); - goto out_free; - } - - err = mtd_torture(libmtd, mtd, args.node_fd, eb); - if (err) { - if (mark_bad(mtd, si, eb)) - goto out_free; - } - continue; - - } - } - - if (!args.quiet && !args.verbose) - printf("\n"); - - if (!novtbl) { - if (eb1 == -1 || eb2 == -1) { - errmsg("no eraseblocks for volume table"); - goto out_free; - } - - verbose(args.verbose, "write volume table to eraseblocks %d and %d", eb1, eb2); - vtbl = ubigen_create_empty_vtbl(ui); - if (!vtbl) - goto out_free; - - err = ubigen_write_layout_vol(ui, eb1, eb2, ec1, ec2, vtbl, - args.node_fd); - free(vtbl); - if (err) { - errmsg("cannot write layout volume"); - goto out_free; - } - } - - free(hdr); - return 0; - -out_free: - free(hdr); - return -1; -} - -int main(int argc, char * const argv[]) -{ - int err, verbose; - libmtd_t libmtd; - struct mtd_info mtd_info; - struct mtd_dev_info mtd; - libubi_t libubi; - struct ubigen_info ui; - struct ubi_scan_info *si; - - libmtd = libmtd_open(); - if (!libmtd) - return errmsg("MTD subsystem is not present"); - - err = parse_opt(argc, argv); - if (err) - goto out_close_mtd; - - err = mtd_get_info(libmtd, &mtd_info); - if (err) { - if (errno == ENODEV) - errmsg("MTD is not present"); - sys_errmsg("cannot get MTD information"); - goto out_close_mtd; - } - - err = mtd_get_dev_info(libmtd, args.node, &mtd); - if (err) { - sys_errmsg("cannot get information about \"%s\"", args.node); - goto out_close_mtd; - } - - if (!is_power_of_2(mtd.min_io_size)) { - errmsg("min. I/O size is %d, but should be power of 2", - mtd.min_io_size); - goto out_close; - } - - if (!mtd_info.sysfs_supported) { - /* - * Linux kernels older than 2.6.30 did not support sysfs - * interface, and it is impossible to find out sub-page - * size in these kernels. This is why users should - * provide -s option. - */ - if (args.subpage_size == 0) { - warnmsg("your MTD system is old and it is impossible " - "to detect sub-page size. Use -s to get rid " - "of this warning"); - normsg("assume sub-page to be %d", mtd.subpage_size); - } else { - mtd.subpage_size = args.subpage_size; - args.manual_subpage = 1; - } - } else if (args.subpage_size && args.subpage_size != mtd.subpage_size) { - mtd.subpage_size = args.subpage_size; - args.manual_subpage = 1; - } - - if (args.manual_subpage) { - /* Do some sanity check */ - if (args.subpage_size > mtd.min_io_size) { - errmsg("sub-page cannot be larger than min. I/O unit"); - goto out_close; - } - - if (mtd.min_io_size % args.subpage_size) { - errmsg("min. I/O unit size should be multiple of " - "sub-page size"); - goto out_close; - } - } - - args.node_fd = open(args.node, O_RDWR); - if (args.node_fd == -1) { - sys_errmsg("cannot open \"%s\"", args.node); - goto out_close_mtd; - } - - /* Validate VID header offset if it was specified */ - if (args.vid_hdr_offs != 0) { - if (args.vid_hdr_offs % 8) { - errmsg("VID header offset has to be multiple of min. I/O unit size"); - goto out_close; - } - if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE > mtd.eb_size) { - errmsg("bad VID header offset"); - goto out_close; - } - } - - if (!mtd.writable) { - errmsg("mtd%d (%s) is a read-only device", mtd.mtd_num, args.node); - goto out_close; - } - - /* Make sure this MTD device is not attached to UBI */ - libubi = libubi_open(); - if (libubi) { - int ubi_dev_num; - - err = mtd_num2ubi_dev(libubi, mtd.mtd_num, &ubi_dev_num); - libubi_close(libubi); - if (!err) { - errmsg("please, first detach mtd%d (%s) from ubi%d", - mtd.mtd_num, args.node, ubi_dev_num); - goto out_close; - } - } - - if (!args.quiet) { - normsg_cont("mtd%d (%s), size ", mtd.mtd_num, mtd.type_str); - ubiutils_print_bytes(mtd.size, 1); - printf(", %d eraseblocks of ", mtd.eb_cnt); - ubiutils_print_bytes(mtd.eb_size, 1); - printf(", min. I/O size %d bytes\n", mtd.min_io_size); - } - - if (args.quiet) - verbose = 0; - else if (args.verbose) - verbose = 2; - else - verbose = 1; - err = ubi_scan(&mtd, args.node_fd, &si, verbose); - if (err) { - errmsg("failed to scan mtd%d (%s)", mtd.mtd_num, args.node); - goto out_close; - } - - if (si->good_cnt == 0) { - errmsg("all %d eraseblocks are bad", si->bad_cnt); - goto out_free; - } - - if (si->good_cnt < 2 && (!args.novtbl || args.image)) { - errmsg("too few non-bad eraseblocks (%d) on mtd%d", - si->good_cnt, mtd.mtd_num); - goto out_free; - } - - if (!args.quiet) { - if (si->ok_cnt) - normsg("%d eraseblocks have valid erase counter, mean value is %lld", - si->ok_cnt, si->mean_ec); - if (si->empty_cnt) - normsg("%d eraseblocks are supposedly empty", si->empty_cnt); - if (si->corrupted_cnt) - normsg("%d corrupted erase counters", si->corrupted_cnt); - print_bad_eraseblocks(&mtd, si); - } - - if (si->alien_cnt) { - if (!args.yes || !args.quiet) - warnmsg("%d of %d eraseblocks contain non-ubifs data", - si->alien_cnt, si->good_cnt); - if (!args.yes && want_exit()) { - if (args.yes && !args.quiet) - printf("yes\n"); - goto out_free; - } - } - - if (!args.override_ec && si->empty_cnt < si->good_cnt) { - int percent = ((double)si->ok_cnt)/si->good_cnt * 100; - - /* - * Make sure the majority of eraseblocks have valid - * erase counters. - */ - if (percent < 50) { - if (!args.yes || !args.quiet) - warnmsg("only %d of %d eraseblocks have valid erase counter", - si->ok_cnt, si->good_cnt); - normsg("erase counter 0 will be used for all eraseblocks"); - normsg("note, arbitrary erase counter value may be specified using -e option"); - if (!args.yes && want_exit()) { - if (args.yes && !args.quiet) - printf("yes\n"); - goto out_free; - } - args.ec = 0; - args.override_ec = 1; - } else if (percent < 95) { - if (!args.yes || !args.quiet) - warnmsg("only %d of %d eraseblocks have valid erase counter", - si->ok_cnt, si->good_cnt); - normsg("mean erase counter %lld will be used for the rest of eraseblock", - si->mean_ec); - if (!args.yes && want_exit()) { - if (args.yes && !args.quiet) - printf("yes\n"); - goto out_free; - } - args.ec = si->mean_ec; - args.override_ec = 1; - } - } - - if (!args.quiet && args.override_ec) - normsg("use erase counter %lld for all eraseblocks", args.ec); - - ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, mtd.subpage_size, - args.vid_hdr_offs, args.ubi_ver, args.image_seq); - - if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) { - /* - * Hmm, what we read from flash and what we calculated using - * min. I/O unit size and sub-page size differs. - */ - if (!args.yes || !args.quiet) { - warnmsg("VID header and data offsets on flash are %d and %d, " - "which is different to requested offsets %d and %d", - si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs, - ui.data_offs); - normsg_cont("use new offsets %d and %d? (yes/no) ", - ui.vid_hdr_offs, ui.data_offs); - } - if (args.yes || answer_is_yes()) { - if (args.yes && !args.quiet) - printf("yes\n"); - } else - ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, 0, - si->vid_hdr_offs, args.ubi_ver, - args.image_seq); - normsg("use offsets %d and %d", ui.vid_hdr_offs, ui.data_offs); - } - - if (args.image) { - err = flash_image(libmtd, &mtd, &ui, si); - if (err < 0) - goto out_free; - - err = format(libmtd, &mtd, &ui, si, err, 1); - if (err) - goto out_free; - } else { - err = format(libmtd, &mtd, &ui, si, 0, args.novtbl); - if (err) - goto out_free; - } - - ubi_scan_free(si); - close(args.node_fd); - libmtd_close(libmtd); - return 0; - -out_free: - ubi_scan_free(si); -out_close: - close(args.node_fd); -out_close_mtd: - libmtd_close(libmtd); - return -1; -} diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/src/ubimkvol.c deleted file mode 100644 index 25065e3..0000000 --- a/ubi-utils/src/ubimkvol.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * An utility to create UBI volumes. - * - * Authors: Artem Bityutskiy <dedekind@infradead.org> - * Frank Haverkamp <haver@vnet.ibm.com> - */ - -#define PROGRAM_VERSION "1.1" -#define PROGRAM_NAME "ubimkvol" - -#include <stdio.h> -#include <stdint.h> -#include <getopt.h> -#include <stdlib.h> -#include <string.h> - -#include <libubi.h> -#include "common.h" -#include "ubiutils-common.h" - -/* The variables below are set by command line arguments */ -struct args { - int vol_id; - int vol_type; - long long bytes; - int lebs; - int alignment; - const char *name; - const char *node; - int maxavs; -}; - -static struct args args = { - .vol_type = UBI_DYNAMIC_VOLUME, - .bytes = -1, - .lebs = -1, - .alignment = 1, - .vol_id = UBI_VOL_NUM_AUTO, -}; - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION - " - a tool to create UBI volumes."; - -static const char optionsstr[] = -"-a, --alignment=<alignment> volume alignment (default is 1)\n" -"-n, --vol_id=<volume ID> UBI volume ID, if not specified, the volume ID\n" -" will be assigned automatically\n" -"-N, --name=<name> volume name\n" -"-s, --size=<bytes> volume size volume size in bytes, kilobytes (KiB)\n" -" or megabytes (MiB)\n" -"-S, --lebs=<LEBs count> alternative way to give volume size in logical\n" -" eraseblocks\n" -"-m, --maxavsize set volume size to maximum available size\n" -"-t, --type=<static|dynamic> volume type (dynamic, static), default is dynamic\n" -"-h, -?, --help print help message\n" -"-V, --version print program version"; - - -static const char usage[] = -"Usage: " PROGRAM_NAME " <UBI device node file name> [-h] [-a <alignment>] [-n <volume ID>] [-N <name>]\n" -"\t\t\t[-s <bytes>] [-S <LEBs>] [-t <static|dynamic>] [-V] [-m]\n" -"\t\t\t[--alignment=<alignment>][--vol_id=<volume ID>] [--name=<name>]\n" -"\t\t\t[--size=<bytes>] [--lebs=<LEBs>] [--type=<static|dynamic>] [--help]\n" -"\t\t\t[--version] [--maxavsize]\n\n" -"Example: " PROGRAM_NAME " /dev/ubi0 -s 20MiB -N config_data - create a 20 Megabytes volume\n" -" named \"config_data\" on UBI device /dev/ubi0."; - -static const struct option long_options[] = { - { .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'a' }, - { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' }, - { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' }, - { .name = "size", .has_arg = 1, .flag = NULL, .val = 's' }, - { .name = "lebs", .has_arg = 1, .flag = NULL, .val = 'S' }, - { .name = "type", .has_arg = 1, .flag = NULL, .val = 't' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { .name = "maxavsize", .has_arg = 0, .flag = NULL, .val = 'm' }, - { NULL, 0, NULL, 0}, -}; - -static int param_sanity_check(void) -{ - int len; - - if (args.bytes == -1 && !args.maxavs && args.lebs == -1) - return errmsg("volume size was not specified (use -h for help)"); - - if ((args.bytes != -1 && (args.maxavs || args.lebs != -1)) || - (args.lebs != -1 && (args.maxavs || args.bytes != -1)) || - (args.maxavs && (args.bytes != -1 || args.lebs != -1))) - return errmsg("size specified with more then one option"); - - if (args.name == NULL) - return errmsg("volume name was not specified (use -h for help)"); - - len = strlen(args.name); - if (len > UBI_MAX_VOLUME_NAME) - return errmsg("too long name (%d symbols), max is %d", len, UBI_MAX_VOLUME_NAME); - - return 0; -} - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key, error = 0; - - key = getopt_long(argc, argv, "a:n:N:s:S:t:h?Vm", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 't': - if (!strcmp(optarg, "dynamic")) - args.vol_type = UBI_DYNAMIC_VOLUME; - else if (!strcmp(optarg, "static")) - args.vol_type = UBI_STATIC_VOLUME; - else - return errmsg("bad volume type: \"%s\"", optarg); - break; - - case 's': - args.bytes = ubiutils_get_bytes(optarg); - if (args.bytes <= 0) - return errmsg("bad volume size: \"%s\"", optarg); - break; - - case 'S': - args.lebs = simple_strtoull(optarg, &error); - if (error || args.lebs <= 0) - return errmsg("bad LEB count: \"%s\"", optarg); - break; - - case 'a': - args.alignment = simple_strtoul(optarg, &error); - if (error || args.alignment <= 0) - return errmsg("bad volume alignment: \"%s\"", optarg); - break; - - case 'n': - args.vol_id = simple_strtoul(optarg, &error); - if (error || args.vol_id < 0) - return errmsg("bad volume ID: " "\"%s\"", optarg); - break; - - case 'N': - args.name = optarg; - break; - - case 'h': - case '?': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - case 'm': - args.maxavs = 1; - break; - - case ':': - return errmsg("parameter is missing"); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (optind == argc) - return errmsg("UBI device name was not specified (use -h for help)"); - else if (optind != argc - 1) - return errmsg("more then one UBI device specified (use -h for help)"); - - args.node = argv[optind]; - - if (param_sanity_check()) - return -1; - - return 0; -} - -int main(int argc, char * const argv[]) -{ - int err; - libubi_t libubi; - struct ubi_dev_info dev_info; - struct ubi_vol_info vol_info; - struct ubi_mkvol_request req; - - err = parse_opt(argc, argv); - if (err) - return err; - - libubi = libubi_open(); - if (!libubi) { - if (errno == 0) - return errmsg("UBI is not present in the system"); - return sys_errmsg("cannot open libubi"); - } - - err = ubi_probe_node(libubi, args.node); - if (err == 2) { - errmsg("\"%s\" is an UBI volume node, not an UBI device node", - args.node); - goto out_libubi; - } else if (err < 0) { - if (errno == ENODEV) - errmsg("\"%s\" is not an UBI device node", args.node); - else - sys_errmsg("error while probing \"%s\"", args.node); - goto out_libubi; - } - - err = ubi_get_dev_info(libubi, args.node, &dev_info); - if (err) { - sys_errmsg("cannot get information about UBI device \"%s\"", - args.node); - goto out_libubi; - } - - if (dev_info.avail_bytes == 0) { - errmsg("UBI device does not have free logical eraseblocks"); - goto out_libubi; - } - - if (args.maxavs) { - args.bytes = dev_info.avail_bytes; - printf("Set volume size to %lld\n", args.bytes); - } - - if (args.lebs != -1) { - args.bytes = dev_info.leb_size; - args.bytes -= dev_info.leb_size % args.alignment; - args.bytes *= args.lebs; - } - - req.vol_id = args.vol_id; - req.alignment = args.alignment; - req.bytes = args.bytes; - req.vol_type = args.vol_type; - req.name = args.name; - - err = ubi_mkvol(libubi, args.node, &req); - if (err < 0) { - sys_errmsg("cannot UBI create volume"); - goto out_libubi; - } - - args.vol_id = req.vol_id; - - /* Print information about the created device */ - err = ubi_get_vol_info1(libubi, dev_info.dev_num, args.vol_id, &vol_info); - if (err) { - sys_errmsg("cannot get information about newly created UBI volume"); - goto out_libubi; - } - - printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs); - ubiutils_print_bytes(vol_info.rsvd_bytes, 0); - printf("), LEB size "); - ubiutils_print_bytes(vol_info.leb_size, 1); - printf(", %s, name \"%s\", alignment %d\n", - req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static", - vol_info.name, vol_info.alignment); - - libubi_close(libubi); - return 0; - -out_libubi: - libubi_close(libubi); - return -1; -} diff --git a/ubi-utils/src/ubinfo.c b/ubi-utils/src/ubinfo.c deleted file mode 100644 index 8e14e6e..0000000 --- a/ubi-utils/src/ubinfo.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Nokia Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * An utility to get UBI information. - * - * Author: Artem Bityutskiy - */ - -#define PROGRAM_VERSION "1.1" -#define PROGRAM_NAME "ubinfo" - -#include <stdint.h> -#include <stdio.h> -#include <getopt.h> -#include <stdlib.h> -#include <string.h> - -#include <libubi.h> -#include "common.h" -#include "ubiutils-common.h" - -/* The variables below are set by command line arguments */ -struct args { - int devn; - int vol_id; - int all; - const char *node; - const char *vol_name; -}; - -static struct args args = { - .vol_id = -1, - .devn = -1, - .all = 0, - .node = NULL, - .vol_name = NULL, -}; - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION - " - a tool to print UBI information."; - -static const char optionsstr[] = -"-d, --devn=<UBI device number> UBI device number to get information about\n" -"-n, --vol_id=<volume ID> ID of UBI volume to print information about\n" -"-N, --name=<volume name> name of UBI volume to print information about\n" -"-a, --all print information about all devices and volumes,\n" -" or about all volumes if the UBI device was\n" -" specified\n" -"-h, --help print help message\n" -"-V, --version print program version"; - -static const char usage[] = -"Usage 1: " PROGRAM_NAME " [-d <UBI device number>] [-n <volume ID> | -N <volume name>] [-a] [-h] [-V]\n" -"\t\t[--vol_id=<volume ID> | --name <volume name>] [--devn <UBI device number>] [--all] [--help] [--version]\n" -"Usage 2: " PROGRAM_NAME " <UBI device node file name> [-a] [-h] [-V] [--all] [--help] [--version]\n" -"Usage 3: " PROGRAM_NAME " <UBI volume node file name> [-h] [-V] [--help] [--version]\n\n" -"Example 1: " PROGRAM_NAME " - (no arguments) print general UBI information\n" -"Example 2: " PROGRAM_NAME " -d 1 - print information about UBI device number 1\n" -"Example 3: " PROGRAM_NAME " /dev/ubi0 -a - print information about all volumes of UBI\n" -" device /dev/ubi0\n" -"Example 4: " PROGRAM_NAME " /dev/ubi1_0 - print information about UBI volume /dev/ubi1_0\n" -"Example 5: " PROGRAM_NAME " -a - print all information\n"; - -static const struct option long_options[] = { - { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' }, - { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' }, - { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' }, - { .name = "all", .has_arg = 0, .flag = NULL, .val = 'a' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0}, -}; - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key, error = 0; - - key = getopt_long(argc, argv, "an:N:d:hV", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'a': - args.all = 1; - break; - - case 'n': - args.vol_id = simple_strtoul(optarg, &error); - if (error || args.vol_id < 0) - return errmsg("bad volume ID: " "\"%s\"", optarg); - break; - - case 'N': - args.vol_name = optarg; - break; - - case 'd': - args.devn = simple_strtoul(optarg, &error); - if (error || args.devn < 0) - return errmsg("bad UBI device number: \"%s\"", optarg); - - break; - - case 'h': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - case ':': - return errmsg("parameter is missing"); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (optind == argc - 1) - args.node = argv[optind]; - else if (optind < argc) - return errmsg("more then one UBI device specified (use -h for help)"); - - return 0; -} - -static int translate_dev(libubi_t libubi, const char *node) -{ - int err; - - err = ubi_probe_node(libubi, node); - if (err == -1) { - if (errno != ENODEV) - return sys_errmsg("error while probing \"%s\"", node); - return errmsg("\"%s\" does not correspond to any UBI device or volume", node); - } - - if (err == 1) { - struct ubi_dev_info dev_info; - - err = ubi_get_dev_info(libubi, node, &dev_info); - if (err) - return sys_errmsg("cannot get information about UBI device \"%s\"", node); - - args.devn = dev_info.dev_num; - } else { - struct ubi_vol_info vol_info; - - err = ubi_get_vol_info(libubi, node, &vol_info); - if (err) - return sys_errmsg("cannot get information about UBI volume \"%s\"", node); - - if (args.vol_id != -1) - return errmsg("both volume character device node (\"%s\") and " - "volume ID (%d) are specify, use only one of them" - "(use -h for help)", node, args.vol_id); - - args.devn = vol_info.dev_num; - args.vol_id = vol_info.vol_id; - } - - return 0; -} - -static int get_vol_id_by_name(libubi_t libubi, int dev_num, const char *name) -{ - int err; - struct ubi_vol_info vol_info; - - err = ubi_get_vol_info1_nm(libubi, dev_num, name, &vol_info); - if (err) - return sys_errmsg("cannot get information about volume \"%s\" on ubi%d\n", name, dev_num); - - args.vol_id = vol_info.vol_id; - - return 0; -} - -static int print_vol_info(libubi_t libubi, int dev_num, int vol_id) -{ - int err; - struct ubi_vol_info vol_info; - - err = ubi_get_vol_info1(libubi, dev_num, vol_id, &vol_info); - if (err) - return sys_errmsg("cannot get information about UBI volume %d on ubi%d", - vol_id, dev_num); - - printf("Volume ID: %d (on ubi%d)\n", vol_info.vol_id, vol_info.dev_num); - printf("Type: %s\n", - vol_info.type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static"); - printf("Alignment: %d\n", vol_info.alignment); - - printf("Size: %d LEBs (", vol_info.rsvd_lebs); - ubiutils_print_bytes(vol_info.rsvd_bytes, 0); - printf(")\n"); - - if (vol_info.type == UBI_STATIC_VOLUME) { - printf("Data bytes: "); - ubiutils_print_bytes(vol_info.data_bytes, 1); - printf("\n"); - } - printf("State: %s\n", vol_info.corrupted ? "corrupted" : "OK"); - printf("Name: %s\n", vol_info.name); - printf("Character device major/minor: %d:%d\n", - vol_info.major, vol_info.minor); - - return 0; -} - -static int print_dev_info(libubi_t libubi, int dev_num, int all) -{ - int i, err, first = 1; - struct ubi_dev_info dev_info; - struct ubi_vol_info vol_info; - - err = ubi_get_dev_info1(libubi, dev_num, &dev_info); - if (err) - return sys_errmsg("cannot get information about UBI device %d", dev_num); - - printf("ubi%d\n", dev_info.dev_num); - printf("Volumes count: %d\n", dev_info.vol_count); - printf("Logical eraseblock size: "); - ubiutils_print_bytes(dev_info.leb_size, 0); - printf("\n"); - - printf("Total amount of logical eraseblocks: %d (", dev_info.total_lebs); - ubiutils_print_bytes(dev_info.total_bytes, 0); - printf(")\n"); - - printf("Amount of available logical eraseblocks: %d (", dev_info.avail_lebs); - ubiutils_print_bytes(dev_info.avail_bytes, 0); - printf(")\n"); - - printf("Maximum count of volumes %d\n", dev_info.max_vol_count); - printf("Count of bad physical eraseblocks: %d\n", dev_info.bad_count); - printf("Count of reserved physical eraseblocks: %d\n", dev_info.bad_rsvd); - printf("Current maximum erase counter value: %lld\n", dev_info.max_ec); - printf("Minimum input/output unit size: %d %s\n", - dev_info.min_io_size, dev_info.min_io_size > 1 ? "bytes" : "byte"); - printf("Character device major/minor: %d:%d\n", - dev_info.major, dev_info.minor); - - if (dev_info.vol_count == 0) - return 0; - - printf("Present volumes: "); - for (i = dev_info.lowest_vol_id; - i <= dev_info.highest_vol_id; i++) { - err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info); - if (err == -1) { - if (errno == ENOENT) - continue; - - return sys_errmsg("libubi failed to probe volume %d on ubi%d", - i, dev_info.dev_num); - } - - if (!first) - printf(", %d", i); - else { - printf("%d", i); - first = 0; - } - } - printf("\n"); - - if (!all) - return 0; - - first = 1; - printf("\n"); - - for (i = dev_info.lowest_vol_id; - i <= dev_info.highest_vol_id; i++) { - if(!first) - printf("-----------------------------------\n"); - err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info); - if (err == -1) { - if (errno == ENOENT) - continue; - - return sys_errmsg("libubi failed to probe volume %d on ubi%d", - i, dev_info.dev_num); - } - first = 0; - - err = print_vol_info(libubi, dev_info.dev_num, i); - if (err) - return err; - } - - return 0; -} - -static int print_general_info(libubi_t libubi, int all) -{ - int i, err, first = 1; - struct ubi_info ubi_info; - struct ubi_dev_info dev_info; - - err = ubi_get_info(libubi, &ubi_info); - if (err) - return sys_errmsg("cannot get UBI information"); - - printf("UBI version: %d\n", ubi_info.version); - printf("Count of UBI devices: %d\n", ubi_info.dev_count); - if (ubi_info.ctrl_major != -1) - printf("UBI control device major/minor: %d:%d\n", - ubi_info.ctrl_major, ubi_info.ctrl_minor); - else - printf("UBI control device is not supported by this kernel\n"); - - if (ubi_info.dev_count == 0) - return 0; - - printf("Present UBI devices: "); - for (i = ubi_info.lowest_dev_num; - i <= ubi_info.highest_dev_num; i++) { - err = ubi_get_dev_info1(libubi, i, &dev_info); - if (err == -1) { - if (errno == ENOENT) - continue; - - printf("\n"); - return sys_errmsg("libubi failed to probe UBI device %d", i); - } - - if (!first) - printf(", ubi%d", i); - else { - printf("ubi%d", i); - first = 0; - } - } - printf("\n"); - - if (!all) - return 0; - - first = 1; - printf("\n"); - - for (i = ubi_info.lowest_dev_num; - i <= ubi_info.highest_dev_num; i++) { - if(!first) - printf("\n===================================\n\n"); - first = 0; - err = print_dev_info(libubi, i, all); - if (err) - return err; - } - return 0; -} - -int main(int argc, char * const argv[]) -{ - int err; - libubi_t libubi; - - err = parse_opt(argc, argv); - if (err) - return -1; - - libubi = libubi_open(); - if (!libubi) { - if (errno == 0) - return errmsg("UBI is not present in the system"); - return sys_errmsg("cannot open libubi"); - } - - if (args.node) { - /* - * A character device was specified, translate this into UBI - * device number and volume ID. - */ - err = translate_dev(libubi, args.node); - if (err) - goto out_libubi; - } - - if (args.vol_name) { - err = get_vol_id_by_name(libubi, args.devn, args.vol_name); - if (err) - goto out_libubi; - } - - if (args.vol_id != -1 && args.devn == -1) { - errmsg("volume ID is specified, but UBI device number is not " - "(use -h for help)\n"); - goto out_libubi; - } - - if (args.devn != -1 && args.vol_id != -1) { - print_vol_info(libubi, args.devn, args.vol_id); - goto out; - } - - if (args.devn == -1 && args.vol_id == -1) - err = print_general_info(libubi, args.all); - else if (args.devn != -1 && args.vol_id == -1) - err = print_dev_info(libubi, args.devn, args.all); - - if (err) - goto out_libubi; - -out: - libubi_close(libubi); - return 0; - -out_libubi: - libubi_close(libubi); - return -1; -} diff --git a/ubi-utils/src/ubinize.c b/ubi-utils/src/ubinize.c deleted file mode 100644 index 3085b66..0000000 --- a/ubi-utils/src/ubinize.c +++ /dev/null @@ -1,628 +0,0 @@ -/* - * Copyright (C) 2008 Nokia Corporation - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Generate UBI images. - * - * Authors: Artem Bityutskiy - * Oliver Lohmann - */ - -#define PROGRAM_VERSION "1.2" -#define PROGRAM_NAME "ubinize" - -#include <sys/stat.h> -#include <stdlib.h> -#include <getopt.h> -#include <string.h> -#include <fcntl.h> - -#include <mtd/ubi-media.h> -#include <libubigen.h> -#include <libiniparser.h> -#include "common.h" -#include "ubiutils-common.h" - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION -" - a tool to generate UBI images. An UBI image may contain one or more UBI " -"volumes which have to be defined in the input configuration ini-file. The " -"ini file defines all the UBI volumes - their characteristics and the and the " -"contents, but it does not define the characteristics of the flash the UBI " -"image is generated for. Instead, the flash characteristics are defined via " -"the command-line options. Note, if not sure about some of the command-line " -"parameters, do not specify them and let the utility to use default values."; - -static const char optionsstr[] = -"-o, --output=<file name> output file name\n" -"-p, --peb-size=<bytes> size of the physical eraseblock of the flash\n" -" this UBI image is created for in bytes,\n" -" kilobytes (KiB), or megabytes (MiB)\n" -" (mandatory parameter)\n" -"-m, --min-io-size=<bytes> minimum input/output unit size of the flash\n" -" in bytes\n" -"-s, --sub-page-size=<bytes> minimum input/output unit used for UBI\n" -" headers, e.g. sub-page size in case of NAND\n" -" flash (equivalent to the minimum input/output\n" -" unit size by default)\n" -"-O, --vid-hdr-offset=<num> offset if the VID header from start of the\n" -" physical eraseblock (default is the next\n" -" minimum I/O unit or sub-page after the EC\n" -" header)\n" -"-e, --erase-counter=<num> the erase counter value to put to EC headers\n" -" (default is 0)\n" -"-x, --ubi-ver=<num> UBI version number to put to EC headers\n" -" (default is 1)\n" -"-Q, --image-seq=<num> 32-bit UBI image sequence number to use\n" -" (by default a random number is picked)\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] [-p <bytes>] [-m <bytes>] [-s <bytes>] [-O <num>] [-e <num>]\n" -"\t\t[-x <num>] [-Q <num>] [-v] [-h] [-V] [--output=<filename>] [--peb-size=<bytes>]\n" -"\t\t[--min-io-size=<bytes>] [--sub-page-size=<bytes>] [--vid-hdr-offset=<num>]\n" -"\t\t[--erase-counter=<num>] [--ubi-ver=<num>] [--image-seq=<num>] [--verbose] [--help]\n" -"\t\t[--version] ini-file\n" -"Example: " PROGRAM_NAME " -o ubi.img -p 16KiB -m 512 -s 256 cfg.ini - create UBI image\n" -" 'ubi.img' as described by configuration file 'cfg.ini'"; - -static const char ini_doc[] = "INI-file format.\n" -"The input configuration ini-file describes all the volumes which have to\n" -"be included to the output UBI image. Each volume is described in its own\n" -"section which may be named arbitrarily. The section consists on\n" -"\"key=value\" pairs, for example:\n\n" -"[jffs2-volume]\n" -"mode=ubi\n" -"image=../jffs2.img\n" -"vol_id=1\n" -"vol_size=30MiB\n" -"vol_type=dynamic\n" -"vol_name=jffs2_volume\n" -"vol_flags=autoresize\n" -"vol_alignment=1\n\n" -"This example configuration file tells the utility to create an UBI image\n" -"with one volume with ID 1, volume size 30MiB, the volume is dynamic, has\n" -"name \"jffs2_volume\", \"autoresize\" volume flag, and alignment 1. The\n" -"\"image=../jffs2.img\" line tells the utility to take the contents of the\n" -"volume from the \"../jffs2.img\" file. The size of the image file has to be\n" -"less or equivalent to the volume size (30MiB). The \"mode=ubi\" line is\n" -"mandatory and just tells that the section describes an UBI volume - other\n" -"section modes may be added in the future.\n" -"Notes:\n" -" * size in vol_size might be specified kilobytes (KiB), megabytes (MiB),\n" -" gigabytes (GiB) or bytes (no modifier);\n" -" * if \"vol_size\" key is absent, the volume size is assumed to be\n" -" equivalent to the size of the image file (defined by \"image\" key);\n" -" * if the \"image\" is absent, the volume is assumed to be empty;\n" -" * volume alignment must not be greater than the logical eraseblock size;\n" -" * one ini file may contain arbitrary number of sections, the utility will\n" -" put all the volumes which are described by these section to the output\n" -" UBI image file."; - -static const 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 = "image-seq", .has_arg = 1, .flag = NULL, .val = 'Q' }, - { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0} -}; - -struct args { - const char *f_in; - const char *f_out; - int out_fd; - int peb_size; - int min_io_size; - int subpage_size; - int vid_hdr_offs; - int ec; - int ubi_ver; - uint32_t image_seq; - int verbose; - dictionary *dict; -}; - -static struct args args = { - .peb_size = -1, - .min_io_size = -1, - .subpage_size = -1, - .ubi_ver = 1, -}; - -static int parse_opt(int argc, char * const argv[]) -{ - ubiutils_srand(); - args.image_seq = rand(); - - while (1) { - int key, error = 0; - unsigned long int image_seq; - - key = getopt_long(argc, argv, "o:p:m:s:O:e:x:Q:vhV", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 'o': - args.out_fd = open(optarg, O_CREAT | O_TRUNC | O_WRONLY, - S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP | S_IROTH); - if (args.out_fd == -1) - return sys_errmsg("cannot open file \"%s\"", optarg); - args.f_out = optarg; - break; - - case 'p': - args.peb_size = ubiutils_get_bytes(optarg); - if (args.peb_size <= 0) - return errmsg("bad physical eraseblock size: \"%s\"", optarg); - break; - - case 'm': - args.min_io_size = ubiutils_get_bytes(optarg); - if (args.min_io_size <= 0) - return errmsg("bad min. I/O unit size: \"%s\"", optarg); - if (!is_power_of_2(args.min_io_size)) - return errmsg("min. I/O unit size should be power of 2"); - break; - - case 's': - args.subpage_size = ubiutils_get_bytes(optarg); - if (args.subpage_size <= 0) - return errmsg("bad sub-page size: \"%s\"", optarg); - if (!is_power_of_2(args.subpage_size)) - return errmsg("sub-page size should be power of 2"); - break; - - case 'O': - args.vid_hdr_offs = simple_strtoul(optarg, &error); - if (error || args.vid_hdr_offs < 0) - return errmsg("bad VID header offset: \"%s\"", optarg); - break; - - case 'e': - args.ec = simple_strtoul(optarg, &error); - if (error || args.ec < 0) - return errmsg("bad erase counter value: \"%s\"", optarg); - break; - - case 'x': - args.ubi_ver = simple_strtoul(optarg, &error); - if (error || args.ubi_ver < 0) - return errmsg("bad UBI version: \"%s\"", optarg); - break; - - case 'Q': - image_seq = simple_strtoul(optarg, &error); - if (error || image_seq > 0xFFFFFFFF) - return errmsg("bad UBI image sequence number: \"%s\"", optarg); - args.image_seq = image_seq; - break; - - case 'v': - args.verbose = 1; - break; - - case 'h': - ubiutils_print_text(stdout, doc, 80); - printf("\n%s\n\n", ini_doc); - printf("%s\n\n", usage); - printf("%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (optind == argc) - return errmsg("input configuration file was not specified (use -h for help)"); - - if (optind != argc - 1) - return errmsg("more then one configuration file was specified (use -h for help)"); - - args.f_in = argv[optind]; - - if (args.peb_size < 0) - return errmsg("physical eraseblock size was not specified (use -h for help)"); - - if (args.peb_size > 1024*1024) - return errmsg("too high physical eraseblock size %d", args.peb_size); - - if (args.min_io_size < 0) - return errmsg("min. I/O unit size was not specified (use -h for help)"); - - if (args.subpage_size < 0) - args.subpage_size = args.min_io_size; - - if (args.subpage_size > args.min_io_size) - return errmsg("sub-page cannot be larger then min. I/O unit"); - - if (args.peb_size % args.min_io_size) - return errmsg("physical eraseblock should be multiple of min. I/O units"); - - if (args.min_io_size % args.subpage_size) - return errmsg("min. I/O unit size should be multiple of sub-page size"); - - if (!args.f_out) - return errmsg("output file was not specified (use -h for help)"); - - if (args.vid_hdr_offs) { - if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE >= args.peb_size) - return errmsg("bad VID header position"); - if (args.vid_hdr_offs % 8) - return errmsg("VID header offset has to be multiple of min. I/O unit size"); - } - - return 0; -} - -static int read_section(const struct ubigen_info *ui, const char *sname, - struct ubigen_vol_info *vi, const char **img, - struct stat *st) -{ - char buf[256]; - const char *p; - - *img = NULL; - - if (strlen(sname) > 128) - return errmsg("too long section name \"%s\"", sname); - - /* Make sure mode is UBI, otherwise ignore this section */ - sprintf(buf, "%s:mode", sname); - p = iniparser_getstring(args.dict, buf, NULL); - if (!p) { - errmsg("\"mode\" key not found in section \"%s\"", sname); - errmsg("the \"mode\" key is mandatory and has to be " - "\"mode=ubi\" if the section describes an UBI volume"); - return -1; - } - - /* If mode is not UBI, skip this section */ - if (strcmp(p, "ubi")) { - verbose(args.verbose, "skip non-ubi section \"%s\"", sname); - return 1; - } - - verbose(args.verbose, "mode=ubi, keep parsing"); - - /* Fetch volume type */ - sprintf(buf, "%s:vol_type", sname); - p = iniparser_getstring(args.dict, buf, NULL); - if (!p) { - normsg("volume type was not specified in " - "section \"%s\", assume \"dynamic\"\n", sname); - vi->type = UBI_VID_DYNAMIC; - } else { - if (!strcmp(p, "static")) - vi->type = UBI_VID_STATIC; - else if (!strcmp(p, "dynamic")) - vi->type = UBI_VID_DYNAMIC; - else - return errmsg("invalid volume type \"%s\" in section \"%s\"", - p, sname); - } - - verbose(args.verbose, "volume type: %s", - vi->type == UBI_VID_DYNAMIC ? "dynamic" : "static"); - - /* Fetch the name of the volume image file */ - sprintf(buf, "%s:image", sname); - p = iniparser_getstring(args.dict, buf, NULL); - if (p) { - *img = p; - if (stat(p, st)) - return sys_errmsg("cannot stat \"%s\" referred from section \"%s\"", - p, sname); - if (st->st_size == 0) - return errmsg("empty file \"%s\" referred from section \"%s\"", - p, sname); - } else if (vi->type == UBI_VID_STATIC) - return errmsg("image is not specified for static volume in section \"%s\"", - sname); - - /* Fetch volume id */ - sprintf(buf, "%s:vol_id", sname); - vi->id = iniparser_getint(args.dict, buf, -1); - if (vi->id == -1) - return errmsg("\"vol_id\" key not found in section \"%s\"", sname); - if (vi->id < 0) - return errmsg("negative volume ID %d in section \"%s\"", - vi->id, sname); - if (vi->id >= ui->max_volumes) - return errmsg("too high volume ID %d in section \"%s\", max. is %d", - vi->id, sname, ui->max_volumes); - - verbose(args.verbose, "volume ID: %d", vi->id); - - /* Fetch volume size */ - sprintf(buf, "%s:vol_size", sname); - p = iniparser_getstring(args.dict, buf, NULL); - if (p) { - vi->bytes = ubiutils_get_bytes(p); - if (vi->bytes <= 0) - return errmsg("bad \"vol_size\" key value \"%s\" (section \"%s\")", - p, sname); - - /* Make sure the image size is not larger than volume size */ - if (*img && st->st_size > vi->bytes) - return errmsg("error in section \"%s\": size of the image file " - "\"%s\" is %lld, which is larger than volume size %lld", - sname, *img, (long long)st->st_size, vi->bytes); - verbose(args.verbose, "volume size: %lld bytes", vi->bytes); - } else { - struct stat st; - - if (!*img) - return errmsg("neither image file (\"image=\") nor volume size " - "(\"vol_size=\") specified in section \"%s\"", sname); - - if (stat(*img, &st)) - return sys_errmsg("cannot stat \"%s\"", *img); - - vi->bytes = st.st_size; - - if (vi->bytes == 0) - return errmsg("file \"%s\" referred from section \"%s\" is empty", - *img, sname); - - normsg_cont("volume size was not specified in section \"%s\", assume" - " minimum to fit image \"%s\"", sname, *img); - ubiutils_print_bytes(vi->bytes, 1); - printf("\n"); - } - - /* Fetch volume name */ - sprintf(buf, "%s:vol_name", sname); - p = iniparser_getstring(args.dict, buf, NULL); - if (!p) - return errmsg("\"vol_name\" key not found in section \"%s\"", sname); - - vi->name = p; - vi->name_len = strlen(p); - if (vi->name_len > UBI_VOL_NAME_MAX) - return errmsg("too long volume name in section \"%s\", max. is %d characters", - vi->name, UBI_VOL_NAME_MAX); - - verbose(args.verbose, "volume name: %s", p); - - /* Fetch volume alignment */ - sprintf(buf, "%s:vol_alignment", sname); - vi->alignment = iniparser_getint(args.dict, buf, -1); - if (vi->alignment == -1) - vi->alignment = 1; - else if (vi->id < 0) - return errmsg("negative volume alignement %d in section \"%s\"", - vi->alignment, sname); - - verbose(args.verbose, "volume alignment: %d", vi->alignment); - - /* Fetch volume flags */ - sprintf(buf, "%s:vol_flags", sname); - p = iniparser_getstring(args.dict, buf, NULL); - if (p) { - if (!strcmp(p, "autoresize")) { - verbose(args.verbose, "autoresize flags found"); - vi->flags |= UBI_VTBL_AUTORESIZE_FLG; - } else { - return errmsg("unknown flags \"%s\" in section \"%s\"", - p, sname); - } - } - - /* Initialize the rest of the volume information */ - vi->data_pad = ui->leb_size % vi->alignment; - vi->usable_leb_size = ui->leb_size - vi->data_pad; - if (vi->type == UBI_VID_DYNAMIC) - vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size; - else - vi->used_ebs = (st->st_size + vi->usable_leb_size - 1) / vi->usable_leb_size; - vi->compat = 0; - return 0; -} - -int main(int argc, char * const argv[]) -{ - int err = -1, sects, i, autoresize_was_already = 0; - struct ubigen_info ui; - struct ubi_vtbl_record *vtbl; - struct ubigen_vol_info *vi; - off_t seek; - - err = parse_opt(argc, argv); - if (err) - return -1; - - ubigen_info_init(&ui, args.peb_size, args.min_io_size, - args.subpage_size, args.vid_hdr_offs, - args.ubi_ver, args.image_seq); - - verbose(args.verbose, "LEB size: %d", ui.leb_size); - verbose(args.verbose, "PEB size: %d", ui.peb_size); - verbose(args.verbose, "min. I/O size: %d", ui.min_io_size); - verbose(args.verbose, "sub-page size: %d", args.subpage_size); - verbose(args.verbose, "VID offset: %d", ui.vid_hdr_offs); - verbose(args.verbose, "data offset: %d", ui.data_offs); - verbose(args.verbose, "UBI image sequence number: %u", ui.image_seq); - - vtbl = ubigen_create_empty_vtbl(&ui); - if (!vtbl) - goto out; - - args.dict = iniparser_load(args.f_in); - if (!args.dict) { - errmsg("cannot load the input ini file \"%s\"", args.f_in); - goto out_vtbl; - } - - verbose(args.verbose, "loaded the ini-file \"%s\"", args.f_in); - - /* Each section describes one volume */ - sects = iniparser_getnsec(args.dict); - if (sects == -1) { - errmsg("ini-file parsing error (iniparser_getnsec)"); - goto out_dict; - } - - verbose(args.verbose, "count of sections: %d", sects); - if (sects == 0) { - errmsg("no sections found the ini-file \"%s\"", args.f_in); - goto out_dict; - } - - if (sects > ui.max_volumes) { - errmsg("too many sections (%d) in the ini-file \"%s\"", - sects, args.f_in); - normsg("each section corresponds to an UBI volume, maximum " - "count of volumes is %d", ui.max_volumes); - goto out_dict; - } - - vi = calloc(sizeof(struct ubigen_vol_info), sects); - if (!vi) { - errmsg("cannot allocate memory"); - goto out_dict; - } - - /* - * Skip 2 PEBs at the beginning of the file for the volume table which - * will be written later. - */ - seek = ui.peb_size * 2; - if (lseek(args.out_fd, seek, SEEK_SET) != seek) { - sys_errmsg("cannot seek file \"%s\"", args.f_out); - goto out_free; - } - - for (i = 0; i < sects; i++) { - const char *sname = iniparser_getsecname(args.dict, i); - const char *img = NULL; - struct stat st; - int fd, j; - - if (!sname) { - errmsg("ini-file parsing error (iniparser_getsecname)"); - goto out_free; - } - - if (args.verbose) - printf("\n"); - verbose(args.verbose, "parsing section \"%s\"", sname); - - err = read_section(&ui, sname, &vi[i], &img, &st); - if (err == -1) - goto out_free; - - verbose(args.verbose, "adding volume %d", vi[i].id); - - /* - * Make sure that volume ID and name is unique and that only - * one volume has auto-resize flag - */ - for (j = 0; j < i; j++) { - if (vi[i].id == vi[j].id) { - errmsg("volume IDs must be unique, but ID %d " - "in section \"%s\" is not", - vi[i].id, sname); - goto out_free; - } - - if (!strcmp(vi[i].name, vi[j].name)) { - errmsg("volume name must be unique, but name " - "\"%s\" in section \"%s\" is not", - vi[i].name, sname); - goto out_free; - } - } - - if (vi[i].flags & UBI_VTBL_AUTORESIZE_FLG) { - if (autoresize_was_already) - return errmsg("only one volume is allowed " - "to have auto-resize flag"); - autoresize_was_already = 1; - } - - err = ubigen_add_volume(&ui, &vi[i], vtbl); - if (err) { - errmsg("cannot add volume for section \"%s\"", sname); - goto out_free; - } - - if (img) { - fd = open(img, O_RDONLY); - if (fd == -1) { - sys_errmsg("cannot open \"%s\"", img); - goto out_free; - } - - verbose(args.verbose, "writing volume %d", vi[i].id); - verbose(args.verbose, "image file: %s", img); - - err = ubigen_write_volume(&ui, &vi[i], args.ec, st.st_size, fd, args.out_fd); - close(fd); - if (err) { - errmsg("cannot write volume for section \"%s\"", sname); - goto out_free; - } - } - - if (args.verbose) - printf("\n"); - } - - verbose(args.verbose, "writing layout volume"); - - err = ubigen_write_layout_vol(&ui, 0, 1, args.ec, args.ec, vtbl, args.out_fd); - if (err) { - errmsg("cannot write layout volume"); - goto out_free; - } - - verbose(args.verbose, "done"); - - free(vi); - iniparser_freedict(args.dict); - free(vtbl); - close(args.out_fd); - return 0; - -out_free: - free(vi); -out_dict: - iniparser_freedict(args.dict); -out_vtbl: - free(vtbl); -out: - close(args.out_fd); - remove(args.f_out); - return err; -} diff --git a/ubi-utils/src/ubirename.c b/ubi-utils/src/ubirename.c deleted file mode 100644 index 070e32e..0000000 --- a/ubi-utils/src/ubirename.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2008 Logitech. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * An utility to get rename UBI volumes. - * - * Author: Richard Titmuss - */ - -#define PROGRAM_VERSION "1.0" -#define PROGRAM_NAME "ubirename" - -#include <stdio.h> -#include <stdint.h> -#include <getopt.h> -#include <stdlib.h> -#include <string.h> - -#include <libubi.h> -#include "common.h" - -static const char usage[] = -"Usage: " PROGRAM_NAME " <UBI device node file name> [<old name> <new name>|...]\n\n" -"Example: " PROGRAM_NAME "/dev/ubi0 A B C D - rename volume A to B, and C to D\n\n" -"This utility allows re-naming several volumes in one go atomically.\n" -"For example, if you have volumes A and B, then you may rename A into B\n" -"and B into A at one go, and the operation will be atomic. This allows\n" -"implementing atomic UBI volumes upgrades. E.g., if you have volume A\n" -"and want to upgrade it atomically, you create a temporary volume B,\n" -"put your new data to B, then rename A to B and B to A, and then you\n" -"may remove old volume B.\n" -"It is also allowed to re-name multiple volumes at a time, but 16 max.\n" -"renames at once, which means you may specify up to 32 volume names.\n" -"If you have volumes A and B, and re-name A to B, bud do not re-name\n" -"B to something else in the same request, old volume B will be removed\n" -"and A will be renamed into B.\n"; - -static int get_vol_id(libubi_t libubi, struct ubi_dev_info *dev_info, - char *name) -{ - int err, i; - struct ubi_vol_info vol_info; - - for (i=dev_info->lowest_vol_id; i<=dev_info->highest_vol_id; i++) { - err = ubi_get_vol_info1(libubi, dev_info->dev_num, i, &vol_info); - if (err == -1) { - if (errno == ENOENT) - continue; - return -1; - } - - if (strcmp(name, vol_info.name) == 0) - return vol_info.vol_id; - } - - return -1; -} - -int main(int argc, char * const argv[]) -{ - int i, err; - int count = 0; - libubi_t libubi; - struct ubi_dev_info dev_info; - struct ubi_rnvol_req rnvol; - const char *node; - - if (argc < 3 || (argc & 1) == 1) { - errmsg("too few arguments"); - fprintf(stderr, "%s\n", usage); - return -1; - } - - if (argc > UBI_MAX_RNVOL + 2) { - errmsg("too many volumes to re-name, max. is %d", - UBI_MAX_RNVOL); - return -1; - } - - node = argv[1]; - libubi = libubi_open(); - if (!libubi) { - if (errno == 0) - return errmsg("UBI is not present in the system"); - return sys_errmsg("cannot open libubi"); - } - - err = ubi_probe_node(libubi, node); - if (err == 2) { - errmsg("\"%s\" is an UBI volume node, not an UBI device node", - node); - goto out_libubi; - } else if (err < 0) { - if (errno == ENODEV) - errmsg("\"%s\" is not an UBI device node", node); - else - sys_errmsg("error while probing \"%s\"", node); - goto out_libubi; - } - - err = ubi_get_dev_info(libubi, node, &dev_info); - if (err == -1) { - sys_errmsg("cannot get information about UBI device \"%s\"", node); - goto out_libubi; - } - - for (i = 2; i < argc; i += 2) { - err = get_vol_id(libubi, &dev_info, argv[i]); - if (err == -1) { - errmsg("\"%s\" volume not found", argv[i]); - goto out_libubi; - } - - rnvol.ents[count].vol_id = err; - rnvol.ents[count].name_len = strlen(argv[i + 1]); - strcpy(rnvol.ents[count++].name, argv[i + 1]); - } - - rnvol.count = count; - - err = ubi_rnvols(libubi, node, &rnvol); - if (err == -1) { - sys_errmsg("cannot rename volumes"); - goto out_libubi; - } - - libubi_close(libubi); - return 0; - -out_libubi: - libubi_close(libubi); - return -1; -} diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/src/ubirmvol.c deleted file mode 100644 index 5725d90..0000000 --- a/ubi-utils/src/ubirmvol.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * An utility to remove UBI volumes. - * - * Authors: Artem Bityutskiy <dedekind@infradead.org> - * Frank Haverkamp <haver@vnet.ibm.com> - */ - -#define PROGRAM_VERSION "1.1" -#define PROGRAM_NAME "ubirmvol" - -#include <stdio.h> -#include <stdint.h> -#include <getopt.h> -#include <stdlib.h> -#include <string.h> - -#include <libubi.h> -#include "common.h" - -/* The variables below are set by command line arguments */ -struct args { - int vol_id; - const char *node; - const char *name; -}; - -static struct args args = { - .vol_id = -1, -}; - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION - " - a tool to remove UBI volumes."; - -static const char optionsstr[] = -"-n, --vol_id=<volume id> volume ID to remove\n" -"-N, --name=<volume name> volume name to remove\n" -"-h, -?, --help print help message\n" -"-V, --version print program version"; - -static const char usage[] = -"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>]\n\n" -" [-N <volume name>] [--name=<volume name>] [-h] [--help]\n\n" -"Example: " PROGRAM_NAME "/dev/ubi0 -n 1 - remove UBI volume 1 from UBI device corresponding\n" -" to /dev/ubi0\n" -" " PROGRAM_NAME "/dev/ubi0 -N my_vol - remove UBI named \"my_vol\" from UBI device\n" -" corresponding to /dev/ubi0"; - -static const struct option long_options[] = { - { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' }, - { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { NULL, 0, NULL, 0}, -}; - -static int param_sanity_check(void) -{ - if (args.vol_id == -1 && !args.name) { - errmsg("please, specify either volume ID or volume name"); - return -1; - } - - if (args.vol_id != -1 && args.name) { - errmsg("please, specify either volume ID or volume name, not both"); - return -1; - } - - return 0; -} - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key, error = 0; - - key = getopt_long(argc, argv, "n:N:h?V", long_options, NULL); - if (key == -1) - break; - - switch (key) { - - case 'n': - args.vol_id = simple_strtoul(optarg, &error); - if (error || args.vol_id < 0) { - errmsg("bad volume ID: " "\"%s\"", optarg); - return -1; - } - break; - - case 'N': - args.name = optarg; - break; - - case 'h': - case '?': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%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 (optind == argc) { - errmsg("UBI device name was not specified (use -h for help)"); - return -1; - } else if (optind != argc - 1) { - errmsg("more then one UBI device specified (use -h for help)"); - return -1; - } - - args.node = argv[optind]; - - if (param_sanity_check()) - return -1; - - return 0; -} - -int main(int argc, char * const argv[]) -{ - int err; - libubi_t libubi; - - err = parse_opt(argc, argv); - if (err) - return -1; - - libubi = libubi_open(); - if (!libubi) { - if (errno == 0) - return errmsg("UBI is not present in the system"); - return sys_errmsg("cannot open libubi"); - } - - err = ubi_probe_node(libubi, args.node); - if (err == 2) { - errmsg("\"%s\" is an UBI volume node, not an UBI device node", - args.node); - goto out_libubi; - } else if (err < 0) { - if (errno == ENODEV) - errmsg("\"%s\" is not an UBI device node", args.node); - else - sys_errmsg("error while probing \"%s\"", args.node); - goto out_libubi; - } - - if (args.name) { - struct ubi_dev_info dev_info; - struct ubi_vol_info vol_info; - - err = ubi_get_dev_info(libubi, args.node, &dev_info); - if (err) { - sys_errmsg("cannot get information about UBI device \"%s\"", - args.node); - goto out_libubi; - } - - err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num, - args.name, &vol_info); - if (err) { - sys_errmsg("cannot find UBI volume \"%s\"", args.name); - goto out_libubi; - } - - args.vol_id = vol_info.vol_id; - } - - err = ubi_rmvol(libubi, args.node, args.vol_id); - if (err) { - sys_errmsg("cannot UBI remove volume"); - goto out_libubi; - } - - libubi_close(libubi); - return 0; - -out_libubi: - libubi_close(libubi); - return -1; -} diff --git a/ubi-utils/src/ubirsvol.c b/ubi-utils/src/ubirsvol.c deleted file mode 100644 index 65f579c..0000000 --- a/ubi-utils/src/ubirsvol.c +++ /dev/null @@ -1,245 +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 resize UBI volumes. - * - * Authors: Artem Bityutskiy <dedekind@infradead.org> - * Frank Haverkamp <haver@vnet.ibm.com> - */ - -#define PROGRAM_VERSION "1.1" -#define PROGRAM_NAME "ubirsvol" - -#include <stdio.h> -#include <stdint.h> -#include <getopt.h> -#include <stdlib.h> -#include <string.h> - -#include <libubi.h> -#include "common.h" -#include "ubiutils-common.h" - -/* The variables below are set by command line arguments */ -struct args { - int vol_id; - const char *node; - const char *name; - long long bytes; - int lebs; -}; - -static struct args args = { - .vol_id = -1, - .bytes = -1, - .lebs = -1, -}; - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION - " - a tool to resize UBI volumes."; - -static const char optionsstr[] = -"-n, --vol_id=<volume id> volume ID to resize\n" -"-N, --name=<volume name> volume name to resize\n" -"-s, --size=<bytes> volume size volume size in bytes, kilobytes (KiB)\n" -" or megabytes (MiB)\n" -"-S, --lebs=<LEBs count> alternative way to give volume size in logical\n" -" eraseblocks\n" -"-h, -?, --help print help message\n" -"-V, --version print program version"; - - -static const char usage[] = -"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>]\n\n" -" [-N <volume name>] [--name=<volume name>] [-s <bytes>] [-S <LEBs>] [-h] [--help]\n\n" -"Example: " PROGRAM_NAME " /dev/ubi0 -n 1 -s 1MiB resize UBI volume 1 to 1 MiB on\n" -" UBI device corresponding to /dev/ubi0\n" -" " PROGRAM_NAME " /dev/ubi0 -N my_vol -s 1MiB - resize UBI volume named \"my_vol\" to 1 MiB\n" -" on UBI device corresponding to /dev/ubi0"; - -static const struct option long_options[] = { - { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' }, - { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { .name = "size", .has_arg = 1, .flag = NULL, .val = 's' }, - { .name = "lebs", .has_arg = 1, .flag = NULL, .val = 'S' }, - { NULL, 0, NULL, 0}, -}; - -static int param_sanity_check(void) -{ - if (args.vol_id == -1 && !args.name) { - errmsg("please, specify either volume ID or volume name"); - return -1; - } - - if (args.vol_id != -1 && args.name) { - errmsg("please, specify either volume ID or volume name, not both"); - return -1; - } - - if (args.bytes == -1 && args.lebs == -1) - return errmsg("volume size was not specified (use -h for help)"); - - if (args.bytes != -1 && args.lebs != -1) - return errmsg("size specified with more then one option"); - - return 0; -} - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key, error = 0; - - key = getopt_long(argc, argv, "s:S:n:N:h?V", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 's': - args.bytes = ubiutils_get_bytes(optarg); - if (args.bytes <= 0) - return errmsg("bad volume size: \"%s\"", optarg); - break; - - case 'S': - args.lebs = simple_strtoull(optarg, &error); - if (error || args.lebs <= 0) - return errmsg("bad LEB count: \"%s\"", optarg); - break; - - case 'n': - args.vol_id = simple_strtoul(optarg, &error); - if (error || args.vol_id < 0) { - errmsg("bad volume ID: " "\"%s\"", optarg); - return -1; - } - break; - - case 'N': - args.name = optarg; - break; - - case 'h': - case '?': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%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 (optind == argc) { - errmsg("UBI device name was not specified (use -h for help)"); - return -1; - } else if (optind != argc - 1) { - errmsg("more then one UBI device specified (use -h for help)"); - return -1; - } - - args.node = argv[optind]; - - if (param_sanity_check()) - return -1; - - return 0; -} - -int main(int argc, char * const argv[]) -{ - int err; - libubi_t libubi; - struct ubi_dev_info dev_info; - struct ubi_vol_info vol_info; - - err = parse_opt(argc, argv); - if (err) - return -1; - - libubi = libubi_open(); - if (!libubi) - return sys_errmsg("cannot open libubi"); - - err = ubi_probe_node(libubi, args.node); - if (err == 2) { - errmsg("\"%s\" is an UBI volume node, not an UBI device node", - args.node); - goto out_libubi; - } else if (err < 0) { - if (errno == ENODEV) - errmsg("\"%s\" is not an UBI device node", args.node); - else - sys_errmsg("error while probing \"%s\"", args.node); - } - - err = ubi_get_dev_info(libubi, args.node, &dev_info); - if (err) { - sys_errmsg("cannot get information about UBI device \"%s\"", - args.node); - goto out_libubi; - } - - if (args.name) { - err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num, - args.name, &vol_info); - if (err) { - sys_errmsg("cannot find UBI volume \"%s\"", args.name); - goto out_libubi; - } - - args.vol_id = vol_info.vol_id; - } else { - err = ubi_get_vol_info1(libubi, dev_info.dev_num, - args.vol_id, &vol_info); - if (err) { - sys_errmsg("cannot find UBI volume ID %d", args.vol_id); - goto out_libubi; - } - } - - if (args.lebs != -1) - args.bytes = vol_info.leb_size * args.lebs; - - err = ubi_rsvol(libubi, args.node, args.vol_id, args.bytes); - if (err) { - sys_errmsg("cannot UBI resize volume"); - goto out_libubi; - } - - libubi_close(libubi); - return 0; - -out_libubi: - libubi_close(libubi); - return -1; -} diff --git a/ubi-utils/src/ubiupdatevol.c b/ubi-utils/src/ubiupdatevol.c deleted file mode 100644 index 24f38fe..0000000 --- a/ubi-utils/src/ubiupdatevol.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * An utility to update UBI volumes. - * - * Authors: Frank Haverkamp - * Joshua W. Boyer - * Artem Bityutskiy - */ - -#define PROGRAM_VERSION "1.2" -#define PROGRAM_NAME "ubiupdatevol" - -#include <fcntl.h> -#include <stdio.h> -#include <stdint.h> -#include <getopt.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/stat.h> - -#include <libubi.h> -#include "common.h" - -struct args { - int truncate; - const char *node; - const char *img; - /* For deprecated -d and -B options handling */ - char dev_name[256]; - int size; - int use_stdin; -}; - -static struct args args; - -static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION - " - a tool to write data to UBI volumes."; - -static const char optionsstr[] = -"-t, --truncate truncate volume (wipe it out)\n" -"-s, --size=<bytes> bytes in input, if not reading from file\n" -"-h, --help print help message\n" -"-V, --version print program version"; - -static const char usage[] = -"Usage: " PROGRAM_NAME " <UBI volume node file name> [-t] [-s <size>] [-h] [-V] [--truncate]\n" -"\t\t\t[--size=<size>] [--help] [--version] <image file>\n\n" -"Example 1: " PROGRAM_NAME " /dev/ubi0_1 fs.img - write file \"fs.img\" to UBI volume /dev/ubi0_1\n" -"Example 2: " PROGRAM_NAME " /dev/ubi0_1 -t - wipe out UBI volume /dev/ubi0_1"; - -static const struct option long_options[] = { - { .name = "truncate", .has_arg = 0, .flag = NULL, .val = 't' }, - { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, - { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' }, - { .name = "size", .has_arg = 1, .flag = NULL, .val = 's' }, - { NULL, 0, NULL, 0} -}; - -static int parse_opt(int argc, char * const argv[]) -{ - while (1) { - int key, error = 0; - - key = getopt_long(argc, argv, "ts:h?V", long_options, NULL); - if (key == -1) - break; - - switch (key) { - case 't': - args.truncate = 1; - break; - - case 's': - args.size = simple_strtoul(optarg, &error); - if (error || args.size < 0) - return errmsg("bad size: " "\"%s\"", optarg); - break; - - case 'h': - case '?': - printf("%s\n\n", doc); - printf("%s\n\n", usage); - printf("%s\n", optionsstr); - exit(EXIT_SUCCESS); - - case 'V': - fprintf(stderr, "%s\n", PROGRAM_VERSION); - exit(EXIT_SUCCESS); - - case ':': - return errmsg("parameter is missing"); - - default: - fprintf(stderr, "Use -h for help\n"); - return -1; - } - } - - if (optind == argc) - return errmsg("UBI device name was not specified (use -h for help)"); - else if (optind != argc - 2 && !args.truncate) - return errmsg("specify UBI device name and image file name as first 2 " - "parameters (use -h for help)"); - - args.node = argv[optind]; - args.img = argv[optind + 1]; - - if (args.img && args.truncate) - return errmsg("You can't truncate and specify an image (use -h for help)"); - - if (args.img && !args.truncate) { - if (strcmp(args.img, "-") == 0) - args.use_stdin = 1; - if (args.use_stdin && !args.size) - return errmsg("file size must be specified if input is stdin"); - } - - return 0; -} - -static int truncate_volume(libubi_t libubi) -{ - int err, fd; - - fd = open(args.node, O_RDWR); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", args.node); - - err = ubi_update_start(libubi, fd, 0); - if (err) { - sys_errmsg("cannot truncate volume \"%s\"", args.node); - close(fd); - return -1; - } - - close(fd); - return 0; -} - -static int ubi_write(int fd, const void *buf, int len) -{ - int ret; - - while (len) { - ret = write(fd, buf, len); - if (ret < 0) { - if (errno == EINTR) { - warnmsg("do not interrupt me!"); - continue; - } - return sys_errmsg("cannot write %d bytes to volume \"%s\"", - len, args.node); - } - - if (ret == 0) - return errmsg("cannot write %d bytes to volume \"%s\"", len, args.node); - - len -= ret; - buf += ret; - } - - return 0; -} - -static int update_volume(libubi_t libubi, struct ubi_vol_info *vol_info) -{ - int err, fd, ifd; - long long bytes; - char *buf; - - buf = malloc(vol_info->leb_size); - if (!buf) - return errmsg("cannot allocate %d bytes of memory", vol_info->leb_size); - - if (!args.size) { - struct stat st; - err = stat(args.img, &st); - if (err < 0) { - errmsg("stat failed on \"%s\"", args.img); - goto out_free; - } - - bytes = st.st_size; - } else - bytes = args.size; - - if (bytes > vol_info->rsvd_bytes) { - errmsg("\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)", - args.img, bytes, args.node, vol_info->rsvd_bytes); - goto out_free; - } - - fd = open(args.node, O_RDWR); - if (fd == -1) { - sys_errmsg("cannot open UBI volume \"%s\"", args.node); - goto out_free; - } - - if (args.use_stdin) - ifd = STDIN_FILENO; - else { - ifd = open(args.img, O_RDONLY); - if (ifd == -1) { - sys_errmsg("cannot open \"%s\"", args.img); - goto out_close1; - } - } - - err = ubi_update_start(libubi, fd, bytes); - if (err) { - sys_errmsg("cannot start volume \"%s\" update", args.node); - goto out_close; - } - - while (bytes) { - int ret, to_copy = vol_info->leb_size; - - if (to_copy > bytes) - to_copy = bytes; - - ret = read(ifd, buf, to_copy); - if (ret <= 0) { - if (errno == EINTR) { - warnmsg("do not interrupt me!"); - continue; - } else { - sys_errmsg("cannot read %d bytes from \"%s\"", - to_copy, args.img); - goto out_close; - } - } - - err = ubi_write(fd, buf, ret); - if (err) - goto out_close; - bytes -= ret; - } - - close(ifd); - close(fd); - free(buf); - return 0; - -out_close: - close(ifd); -out_close1: - close(fd); -out_free: - free(buf); - return -1; -} - -int main(int argc, char * const argv[]) -{ - int err; - libubi_t libubi; - struct ubi_vol_info vol_info; - - err = parse_opt(argc, argv); - if (err) - return -1; - - libubi = libubi_open(); - if (!libubi) { - if (errno == 0) - errmsg("UBI is not present in the system"); - else - sys_errmsg("cannot open libubi"); - goto out_libubi; - } - - err = ubi_probe_node(libubi, args.node); - if (err == 1) { - errmsg("\"%s\" is an UBI device node, not an UBI volume node", - args.node); - goto out_libubi; - } else if (err < 0) { - if (errno == ENODEV) - errmsg("\"%s\" is not an UBI volume node", args.node); - else - sys_errmsg("error while probing \"%s\"", args.node); - goto out_libubi; - } - - err = ubi_get_vol_info(libubi, args.node, &vol_info); - if (err) { - sys_errmsg("cannot get information about UBI volume \"%s\"", - args.node); - goto out_libubi; - } - - if (args.truncate) - err = truncate_volume(libubi); - else - err = update_volume(libubi, &vol_info); - if (err) - goto out_libubi; - - libubi_close(libubi); - return 0; - -out_libubi: - libubi_close(libubi); - return -1; -} diff --git a/ubi-utils/src/ubiutils-common.c b/ubi-utils/src/ubiutils-common.c deleted file mode 100644 index 6609a6b..0000000 --- a/ubi-utils/src/ubiutils-common.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * This file contains various common stuff used by UBI utilities. - * - * Authors: Artem Bityutskiy - * Adrian Hunter - */ - -#define PROGRAM_NAME "ubiutils" - -#include <sys/time.h> -#include <sys/types.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <stdlib.h> -#include <unistd.h> -#include "common.h" - -/** - * get_multiplier - convert size specifier to an integer multiplier. - * @str: the size specifier string - * - * This function parses the @str size specifier, which may be one of - * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive - * size multiplier in case of success and %-1 in case of failure. - */ -static int get_multiplier(const char *str) -{ - if (!str) - return 1; - - /* Remove spaces before the specifier */ - while (*str == ' ' || *str == '\t') - str += 1; - - if (!strcmp(str, "KiB")) - return 1024; - if (!strcmp(str, "MiB")) - return 1024 * 1024; - if (!strcmp(str, "GiB")) - return 1024 * 1024 * 1024; - - return -1; -} - -/** - * ubiutils_get_bytes - convert a string containing amount of bytes into an - * integer - * @str: string to convert - * - * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB' - * size specifiers. Returns positive amount of bytes in case of success and %-1 - * in case of failure. - */ -long long ubiutils_get_bytes(const char *str) -{ - char *endp; - long long bytes = strtoull(str, &endp, 0); - - if (endp == str || bytes < 0) { - fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str); - return -1; - } - - if (*endp != '\0') { - int mult = get_multiplier(endp); - - if (mult == -1) { - fprintf(stderr, "bad size specifier: \"%s\" - " - "should be 'KiB', 'MiB' or 'GiB'\n", endp); - return -1; - } - bytes *= mult; - } - - return bytes; -} - -/** - * ubiutils_print_bytes - print bytes. - * @bytes: variable to print - * @bracket: whether brackets have to be put or not - * - * This is a helper function which prints amount of bytes in a human-readable - * form, i.e., it prints the exact amount of bytes following by the approximate - * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes - * is. - */ -void ubiutils_print_bytes(long long bytes, int bracket) -{ - const char *p; - - if (bracket) - p = " ("; - else - p = ", "; - - printf("%lld bytes", bytes); - - if (bytes > 1024 * 1024 * 1024) - printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024)); - else if (bytes > 1024 * 1024) - printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024)); - else if (bytes > 1024 && bytes != 0) - printf("%s%.1f KiB", p, (double)bytes / 1024); - else - return; - - if (bracket) - printf(")"); -} - -/** - * ubiutils_print_text - print text and fold it. - * @stream: file stream to print to - * @text: text to print - * @width: maximum allowed text width - * - * Print text and fold it so that each line would not have more then @width - * characters. - */ -void ubiutils_print_text(FILE *stream, const char *text, int width) -{ - int pos, bpos = 0; - const char *p; - char line[1024]; - - if (width > 1023) { - fprintf(stream, "%s\n", text); - return; - } - p = text; - pos = 0; - while (p[pos]) { - while (!isspace(p[pos])) { - line[pos] = p[pos]; - if (!p[pos]) - break; - ++pos; - if (pos == width) { - line[pos] = '\0'; - fprintf(stream, "%s\n", line); - p += pos; - pos = 0; - } - } - while (pos < width) { - line[pos] = p[pos]; - if (!p[pos]) { - bpos = pos; - break; - } - if (isspace(p[pos])) - bpos = pos; - ++pos; - } - line[bpos] = '\0'; - fprintf(stream, "%s\n", line); - p += bpos; - pos = 0; - while (p[pos] && isspace(p[pos])) - ++p; - } -} - -/** - * ubiutils_srand - randomly seed the standard pseudo-random generator. - * - * This helper function seeds the standard libc pseudo-random generator with a - * more or less random value to make sure the 'rand()' call does not return the - * same sequence every time UBI utilities run. Returns zero in case of success - * and a %-1 in case of error. - */ -int ubiutils_srand(void) -{ - struct timeval tv; - struct timezone tz; - unsigned int seed; - - /* - * Just assume that a combination of the PID + current time is a - * reasonably random number. - */ - if (gettimeofday(&tv, &tz)) - return -1; - - seed = (unsigned int)tv.tv_sec; - seed += (unsigned int)tv.tv_usec; - seed *= getpid(); - seed %= RAND_MAX; - srand(seed); - return 0; -} |