diff options
Diffstat (limited to 'ubi-utils/src')
-rw-r--r-- | ubi-utils/src/common.h | 87 | ||||
-rw-r--r-- | ubi-utils/src/crc32.c | 95 | ||||
-rw-r--r-- | ubi-utils/src/crc32.h | 17 | ||||
-rw-r--r-- | ubi-utils/src/libmtd.c | 1157 | ||||
-rw-r--r-- | ubi-utils/src/libmtd_int.h | 88 | ||||
-rw-r--r-- | ubi-utils/src/libmtd_legacy.c | 359 | ||||
-rw-r--r-- | ubi-utils/src/libscan.c | 2 | ||||
-rw-r--r-- | ubi-utils/src/libubigen.c | 2 | ||||
-rw-r--r-- | ubi-utils/src/ubicrc32.c | 2 | ||||
-rw-r--r-- | ubi-utils/src/ubiformat.c | 2 |
10 files changed, 4 insertions, 1807 deletions
diff --git a/ubi-utils/src/common.h b/ubi-utils/src/common.h deleted file mode 100644 index d14cb48..0000000 --- a/ubi-utils/src/common.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) Artem Bityutskiy, 2007, 2008 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __UBI_UTILS_COMMON_H__ -#define __UBI_UTILS_COMMON_H__ - -#include <stdio.h> -#include <ctype.h> -#include <string.h> -#include <errno.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define MIN(a ,b) ((a) < (b) ? (a) : (b)) -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - -/* Verbose messages */ -#define verbose(verbose, fmt, ...) do { \ - if (verbose) \ - printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \ -} while(0) - -/* Normal messages */ -#define normsg(fmt, ...) do { \ - printf(PROGRAM_NAME ": " fmt "\n", ##__VA_ARGS__); \ -} while(0) -#define normsg_cont(fmt, ...) do { \ - printf(PROGRAM_NAME ": " fmt, ##__VA_ARGS__); \ -} while(0) -#define normsg_cont(fmt, ...) do { \ - printf(PROGRAM_NAME ": " fmt, ##__VA_ARGS__); \ -} while(0) - -/* Error messages */ -#define errmsg(fmt, ...) ({ \ - fprintf(stderr, PROGRAM_NAME ": error!: " fmt "\n", ##__VA_ARGS__); \ - -1; \ -}) - -/* System error messages */ -#define sys_errmsg(fmt, ...) ({ \ - int _err = errno; \ - size_t _i; \ - fprintf(stderr, PROGRAM_NAME ": error!: " fmt "\n", ##__VA_ARGS__); \ - for (_i = 0; _i < sizeof(PROGRAM_NAME) + 1; _i++) \ - fprintf(stderr, " "); \ - fprintf(stderr, "error %d (%s)\n", _err, strerror(_err)); \ - -1; \ -}) - -/* Warnings */ -#define warnmsg(fmt, ...) do { \ - fprintf(stderr, PROGRAM_NAME ": warning!: " fmt "\n", ##__VA_ARGS__); \ -} while(0) - -static inline int is_power_of_2(unsigned long long n) -{ - return (n != 0 && ((n & (n - 1)) == 0)); -} - -long long ubiutils_get_bytes(const char *str); -void ubiutils_print_bytes(long long bytes, int bracket); -void ubiutils_print_text(FILE *stream, const char *txt, int len); -int ubiutils_srand(void); - -#ifdef __cplusplus -} -#endif - -#endif /* !__UBI_UTILS_COMMON_H__ */ diff --git a/ubi-utils/src/crc32.c b/ubi-utils/src/crc32.c deleted file mode 100644 index 6b1e50c..0000000 --- a/ubi-utils/src/crc32.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - * code or tables extracted from it, as desired without restriction. - * - * First, the polynomial itself and its table of feedback terms. The - * polynomial is - * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 - * - * Note that we take it "backwards" and put the highest-order term in - * the lowest-order bit. The X^32 term is "implied"; the LSB is the - * X^31 term, etc. The X^0 term (usually shown as "+1") results in - * the MSB being 1 - * - * Note that the usual hardware shift register implementation, which - * is what we're using (we're merely optimizing it by doing eight-bit - * chunks at a time) shifts bits into the lowest-order term. In our - * implementation, that means shifting towards the right. Why do we - * do it this way? Because the calculated CRC must be transmitted in - * order from highest-order term to lowest-order term. UARTs transmit - * characters in order from LSB to MSB. By storing the CRC this way - * we hand it to the UART in the order low-byte to high-byte; the UART - * sends each low-bit to hight-bit; and the result is transmission bit - * by bit from highest- to lowest-order term without requiring any bit - * shuffling on our part. Reception works similarly - * - * The feedback terms table consists of 256, 32-bit entries. Notes - * - * The table can be generated at runtime if desired; code to do so - * is shown later. It might not be obvious, but the feedback - * terms simply represent the results of eight shift/xor opera - * tions for all combinations of data and CRC register values - * - * The values must be right-shifted by eight bits by the "updcrc - * logic; the shift must be unsigned (bring in zeroes). On some - * hardware you could probably optimize the shift in assembler by - * using byte-swap instructions - * polynomial $edb88320 - */ - -#include <stdint.h> - -const uint32_t crc32_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; diff --git a/ubi-utils/src/crc32.h b/ubi-utils/src/crc32.h deleted file mode 100644 index c001fcf..0000000 --- a/ubi-utils/src/crc32.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __CRC32_H__ -#define __CRC32_H__ - -#include <stdint.h> - -extern const uint32_t crc32_table[256]; - -/* Returns a 32-bit CRC of the contents of the buffer */ -static inline uint32_t crc32(uint32_t val, const void *ss, int len) -{ - const unsigned char *s = ss; - while (--len >= 0) - val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); - return val; -} - -#endif diff --git a/ubi-utils/src/libmtd.c b/ubi-utils/src/libmtd.c deleted file mode 100644 index 3ff031c..0000000 --- a/ubi-utils/src/libmtd.c +++ /dev/null @@ -1,1157 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * 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 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 - * - * MTD library. - */ - -#include <limits.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <dirent.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <mtd/mtd-user.h> - -#include <libmtd.h> -#include "libmtd_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_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 success, 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_get_major - get major and minor numbers of an MTD device. - * @lib: libmtd descriptor - * @mtd_num: MTD device number - * @major: major number is returned here - * @minor: minor number is returned here - * - * This function returns zero in case of success and %-1 in case of failure. - */ -static int dev_get_major(struct libmtd *lib, int mtd_num, int *major, int *minor) -{ - char file[strlen(lib->mtd_dev) + 50]; - - sprintf(file, lib->mtd_dev, mtd_num); - return read_major(file, major, minor); -} - -/** - * dev_read_data - read data from an MTD device's sysfs file. - * @patt: file pattern to read from - * @mtd_num: MTD device number - * @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 dev_read_data(const char *patt, int mtd_num, void *buf, int buf_len) -{ - char file[strlen(patt) + 100]; - - sprintf(file, patt, mtd_num); - return read_data(file, buf, buf_len); -} - -/** - * read_hex_ll - read a hex '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 hexadecimal - * '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_hex_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, "%llx\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_pos_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_pos_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, 50); - if (rd == -1) { - sys_errmsg("cannot read \"%s\"", file); - goto out_error; - } - if (rd == 50) { - errmsg("contents of \"%s\" is too long", file); - errno = EINVAL; - goto out_error; - } - - 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_hex_int - read an 'int' value from a file. - * @file: the file to read from - * @value: the result is stored here - * - * This function is the same as 'read_pos_ll()', but it reads an 'int' - * value, not 'long long'. - */ -static int read_hex_int(const char *file, int *value) -{ - long long res; - - if (read_hex_ll(file, &res)) - return -1; - - /* Make sure the value has correct range */ - if (res > INT_MAX || res < INT_MIN) { - errmsg("value %lld read from file \"%s\" is out of range", - res, file); - errno = EINVAL; - return -1; - } - - *value = res; - return 0; -} - -/** - * read_pos_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_pos_ll()', but it reads an 'int' - * value, not 'long long'. - */ -static int read_pos_int(const char *file, int *value) -{ - long long res; - - if (read_pos_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; -} - -/** - * dev_read_hex_int - read an hex 'int' value from an MTD device sysfs file. - * @patt: file pattern to read from - * @mtd_num: MTD 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_hex_int(const char *patt, int mtd_num, int *value) -{ - char file[strlen(patt) + 50]; - - sprintf(file, patt, mtd_num); - return read_hex_int(file, value); -} - -/** - * dev_read_pos_int - read a positive 'int' value from an MTD device sysfs file. - * @patt: file pattern to read from - * @mtd_num: MTD 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_pos_int(const char *patt, int mtd_num, int *value) -{ - char file[strlen(patt) + 50]; - - sprintf(file, patt, mtd_num); - return read_pos_int(file, value); -} - -/** - * dev_read_pos_ll - read a positive 'long long' value from an MTD device sysfs file. - * @patt: file pattern to read from - * @mtd_num: MTD 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_pos_ll(const char *patt, int mtd_num, long long *value) -{ - char file[strlen(patt) + 50]; - - sprintf(file, patt, mtd_num); - return read_pos_ll(file, value); -} - -/** - * type_str2int - convert MTD device type to integer. - * @str: MTD device type string to convert - * - * This function converts MTD device type string @str, read from sysfs, into an - * integer. - */ -static int type_str2int(const char *str) -{ - if (!strcmp(str, "nand")) - return MTD_NANDFLASH; - if (!strcmp(str, "nor")) - return MTD_NORFLASH; - if (!strcmp(str, "rom")) - return MTD_ROM; - if (!strcmp(str, "absent")) - return MTD_ABSENT; - if (!strcmp(str, "dataflash")) - return MTD_DATAFLASH; - if (!strcmp(str, "ram")) - return MTD_RAM; - if (!strcmp(str, "ubi")) - return MTD_UBIVOLUME; - return -1; -} - -/** - * dev_node2num - find UBI device number by its character device node. - * @lib: MTD library descriptor - * @node: name of the MTD device node - * @mtd_num: MTD device number is returned here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int dev_node2num(struct libmtd *lib, const char *node, int *mtd_num) -{ - struct stat st; - int i, major, minor; - struct mtd_info info; - - 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 (mtd_get_info((libmtd_t *)lib, &info)) - return -1; - - for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) { - int major1, minor1, ret; - - ret = dev_get_major(lib, i, &major1, &minor1); - if (ret) { - if (errno == ENOENT) - continue; - if (!errno) - break; - return -1; - } - - if (major1 == major && minor1 == minor) { - errno = 0; - *mtd_num = i; - return 0; - } - } - - errno = ENODEV; - return -1; -} - -/** - * sysfs_is_supported - check whether the MTD sub-system supports MTD. - * @lib: MTD library descriptor - * - * The Linux kernel MTD subsystem gained MTD support starting from kernel - * 2.6.30 and libmtd tries to use sysfs interface if possible, because the NAND - * sub-page size is available there (and not available at all in pre-sysfs - * kernels). - * - * Very old kernels did not have "/sys/class/mtd" directory. Not very old - * kernels (e.g., 2.6.29) did have "/sys/class/mtd/mtdX" directories, by there - * were no files there, e.g., the "name" file was not present. So all we can do - * is to check for a "/sys/class/mtd/mtdX/name" file. But this is not a - * reliable check, because if this is a new system with no MTD devices - we'll - * treat it as a pre-sysfs system. - */ -static int sysfs_is_supported(struct libmtd *lib) -{ - int fd, num = -1; - DIR *sysfs_mtd; - char file[strlen(lib->mtd_name) + 10]; - - sysfs_mtd = opendir(lib->sysfs_mtd); - if (!sysfs_mtd) { - if (errno == ENOENT) { - errno = 0; - return 0; - } - return sys_errmsg("cannot open \"%s\"", lib->sysfs_mtd); - } - - /* - * First of all find an "mtdX" directory. This is needed because there - * may be, for example, mtd1 but no mtd0. - */ - while (1) { - int ret, mtd_num; - char tmp_buf[256]; - struct dirent *dirent; - - dirent = readdir(sysfs_mtd); - if (!dirent) - break; - - if (strlen(dirent->d_name) >= 255) { - errmsg("invalid entry in %s: \"%s\"", - lib->sysfs_mtd, dirent->d_name); - errno = EINVAL; - closedir(sysfs_mtd); - return -1; - } - - ret = sscanf(dirent->d_name, MTD_NAME_PATT"%s", - &mtd_num, tmp_buf); - if (ret == 1) { - num = mtd_num; - break; - } - } - - if (closedir(sysfs_mtd)) - return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_mtd); - - if (num == -1) - /* No mtd device, treat this as pre-sysfs system */ - return 0; - - sprintf(file, lib->mtd_name, num); - fd = open(file, O_RDONLY); - if (fd == -1) - return 0; - - if (close(fd)) { - sys_errmsg("close failed on \"%s\"", file); - return -1; - } - - return 1; -} - -libmtd_t libmtd_open(void) -{ - struct libmtd *lib; - - lib = calloc(1, sizeof(struct libmtd)); - if (!lib) - return NULL; - - lib->sysfs_mtd = mkpath("/sys", SYSFS_MTD); - if (!lib->sysfs_mtd) - goto out_error; - - lib->mtd = mkpath(lib->sysfs_mtd, MTD_NAME_PATT); - if (!lib->mtd) - goto out_error; - - lib->mtd_name = mkpath(lib->mtd, MTD_NAME); - if (!lib->mtd_name) - goto out_error; - - if (!sysfs_is_supported(lib)) { - free(lib->mtd); - free(lib->sysfs_mtd); - free(lib->mtd_name); - lib->mtd_name = lib->mtd = lib->sysfs_mtd = NULL; - return lib; - } - - lib->mtd_dev = mkpath(lib->mtd, MTD_DEV); - if (!lib->mtd_dev) - goto out_error; - - lib->mtd_type = mkpath(lib->mtd, MTD_TYPE); - if (!lib->mtd_type) - goto out_error; - - lib->mtd_eb_size = mkpath(lib->mtd, MTD_EB_SIZE); - if (!lib->mtd_eb_size) - goto out_error; - - lib->mtd_size = mkpath(lib->mtd, MTD_SIZE); - if (!lib->mtd_size) - goto out_error; - - lib->mtd_min_io_size = mkpath(lib->mtd, MTD_MIN_IO_SIZE); - if (!lib->mtd_min_io_size) - goto out_error; - - lib->mtd_subpage_size = mkpath(lib->mtd, MTD_SUBPAGE_SIZE); - if (!lib->mtd_subpage_size) - goto out_error; - - lib->mtd_oob_size = mkpath(lib->mtd, MTD_OOB_SIZE); - if (!lib->mtd_oob_size) - goto out_error; - - lib->mtd_region_cnt = mkpath(lib->mtd, MTD_REGION_CNT); - if (!lib->mtd_region_cnt) - goto out_error; - - lib->mtd_flags = mkpath(lib->mtd, MTD_FLAGS); - if (!lib->mtd_flags) - goto out_error; - - lib->sysfs_supported = 1; - return lib; - -out_error: - libmtd_close((libmtd_t)lib); - return NULL; -} - -void libmtd_close(libmtd_t desc) -{ - struct libmtd *lib = (struct libmtd *)desc; - - free(lib->mtd_flags); - free(lib->mtd_region_cnt); - free(lib->mtd_oob_size); - free(lib->mtd_subpage_size); - free(lib->mtd_min_io_size); - free(lib->mtd_size); - free(lib->mtd_eb_size); - free(lib->mtd_type); - free(lib->mtd_dev); - free(lib->mtd_name); - free(lib->mtd); - free(lib->sysfs_mtd); - free(lib); -} - -int mtd_get_info(libmtd_t desc, struct mtd_info *info) -{ - DIR *sysfs_mtd; - struct dirent *dirent; - struct libmtd *lib = (struct libmtd *)desc; - - memset(info, 0, sizeof(struct mtd_info)); - - if (!lib->sysfs_supported) - return legacy_mtd_get_info(info); - - info->sysfs_supported = 1; - - /* - * We have to scan the MTD sysfs directory to identify how many MTD - * devices are present. - */ - sysfs_mtd = opendir(lib->sysfs_mtd); - if (!sysfs_mtd) { - if (errno == ENOENT) { - errno = ENODEV; - return -1; - } - return sys_errmsg("cannot open \"%s\"", lib->sysfs_mtd); - } - - info->lowest_mtd_num = INT_MAX; - while (1) { - int mtd_num, ret; - char tmp_buf[256]; - - errno = 0; - dirent = readdir(sysfs_mtd); - if (!dirent) - break; - - if (strlen(dirent->d_name) >= 255) { - errmsg("invalid entry in %s: \"%s\"", - lib->sysfs_mtd, dirent->d_name); - errno = EINVAL; - goto out_close; - } - - ret = sscanf(dirent->d_name, MTD_NAME_PATT"%s", - &mtd_num, tmp_buf); - if (ret == 1) { - info->mtd_dev_cnt += 1; - if (mtd_num > info->highest_mtd_num) - info->highest_mtd_num = mtd_num; - if (mtd_num < info->lowest_mtd_num) - info->lowest_mtd_num = mtd_num; - } - } - - if (!dirent && errno) { - sys_errmsg("readdir failed on \"%s\"", lib->sysfs_mtd); - goto out_close; - } - - if (closedir(sysfs_mtd)) - return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_mtd); - - if (info->lowest_mtd_num == INT_MAX) - info->lowest_mtd_num = 0; - - return 0; - -out_close: - closedir(sysfs_mtd); - return -1; -} - -int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd) -{ - int ret; - struct stat st; - struct libmtd *lib = (struct libmtd *)desc; - - memset(mtd, 0, sizeof(struct mtd_dev_info)); - mtd->mtd_num = mtd_num; - - if (!lib->sysfs_supported) - return legacy_get_dev_info1(mtd_num, mtd); - else { - char file[strlen(lib->mtd) + 10]; - - sprintf(file, lib->mtd, mtd_num); - if (stat(file, &st)) { - if (errno == ENOENT) - errno = ENODEV; - return -1; - } - } - - if (dev_get_major(lib, mtd_num, &mtd->major, &mtd->minor)) - return -1; - - ret = dev_read_data(lib->mtd_name, mtd_num, &mtd->name, - MTD_NAME_MAX + 1); - if (ret < 0) - return -1; - ((char *)mtd->name)[ret - 1] = '\0'; - - ret = dev_read_data(lib->mtd_type, mtd_num, &mtd->type_str, - MTD_TYPE_MAX + 1); - if (ret < 0) - return -1; - ((char *)mtd->type_str)[ret - 1] = '\0'; - - if (dev_read_pos_int(lib->mtd_eb_size, mtd_num, &mtd->eb_size)) - return -1; - if (dev_read_pos_ll(lib->mtd_size, mtd_num, &mtd->size)) - return -1; - if (dev_read_pos_int(lib->mtd_min_io_size, mtd_num, &mtd->min_io_size)) - return -1; - if (dev_read_pos_int(lib->mtd_subpage_size, mtd_num, &mtd->subpage_size)) - return -1; - if (dev_read_pos_int(lib->mtd_oob_size, mtd_num, &mtd->oob_size)) - return -1; - if (dev_read_pos_int(lib->mtd_region_cnt, mtd_num, &mtd->region_cnt)) - return -1; - if (dev_read_hex_int(lib->mtd_flags, mtd_num, &ret)) - return -1; - mtd->writable = !!(ret & MTD_WRITEABLE); - - mtd->eb_cnt = mtd->size / mtd->eb_size; - mtd->type = type_str2int(mtd->type_str); - mtd->bb_allowed = !!(mtd->type == MTD_NANDFLASH); - - return 0; -} - -int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd) -{ - int mtd_num; - struct libmtd *lib = (struct libmtd *)desc; - - if (!lib->sysfs_supported) - return legacy_get_dev_info(node, mtd); - - if (dev_node2num(lib, node, &mtd_num)) - return -1; - - return mtd_get_dev_info1(desc, mtd_num, mtd); -} - -int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb) -{ - struct erase_info_user ei; - - ei.start = eb * mtd->eb_size;; - ei.length = mtd->eb_size; - return ioctl(fd, MEMERASE, &ei); -} - -/* Patterns to write to a physical eraseblock when torturing it */ -static uint8_t patterns[] = {0xa5, 0x5a, 0x0}; - -/** - * check_pattern - check if buffer contains only a certain byte pattern. - * @buf: buffer to check - * @patt: the pattern to check - * @size: buffer size in bytes - * - * This function returns %1 in there are only @patt bytes in @buf, and %0 if - * something else was also found. - */ -static int check_pattern(const void *buf, uint8_t patt, int size) -{ - int i; - - for (i = 0; i < size; i++) - if (((const uint8_t *)buf)[i] != patt) - return 0; - return 1; -} - -int mtd_torture(const struct mtd_dev_info *mtd, int fd, int eb) -{ - int err, i, patt_count; - void *buf; - - normsg("run torture test for PEB %d", eb); - patt_count = ARRAY_SIZE(patterns); - - buf = malloc(mtd->eb_size); - if (!buf) { - errmsg("cannot allocate %d bytes of memory", mtd->eb_size); - return -1; - } - - for (i = 0; i < patt_count; i++) { - err = mtd_erase(mtd, fd, eb); - if (err) - goto out; - - /* Make sure the PEB contains only 0xFF bytes */ - err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size); - if (err) - goto out; - - err = check_pattern(buf, 0xFF, mtd->eb_size); - if (err == 0) { - errmsg("erased PEB %d, but a non-0xFF byte found", eb); - errno = EIO; - goto out; - } - - /* Write a pattern and check it */ - memset(buf, patterns[i], mtd->eb_size); - err = mtd_write(mtd, fd, eb, 0, buf, mtd->eb_size); - if (err) - goto out; - - memset(buf, ~patterns[i], mtd->eb_size); - err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size); - if (err) - goto out; - - err = check_pattern(buf, patterns[i], mtd->eb_size); - if (err == 0) { - errmsg("pattern %x checking failed for PEB %d", - patterns[i], eb); - errno = EIO; - goto out; - } - } - - err = 0; - normsg("PEB %d passed torture test, do not mark it a bad", eb); - -out: - free(buf); - return -1; -} - -int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb) -{ - int ret; - loff_t seek; - - if (eb < 0 || eb >= mtd->eb_cnt) { - errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", - eb, mtd->mtd_num, mtd->eb_cnt); - errno = EINVAL; - return -1; - } - - if (!mtd->bb_allowed) - return 0; - - seek = (loff_t)eb * mtd->eb_size; - ret = ioctl(fd, MEMGETBADBLOCK, &seek); - if (ret == -1) - return sys_errmsg("MEMGETBADBLOCK ioctl failed for " - "eraseblock %d (mtd%d)", eb, mtd->mtd_num); - return ret; -} - -int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb) -{ - int ret; - loff_t seek; - - if (!mtd->bb_allowed) { - errno = EINVAL; - return -1; - } - - if (eb < 0 || eb >= mtd->eb_cnt) { - errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", - eb, mtd->mtd_num, mtd->eb_cnt); - errno = EINVAL; - return -1; - } - - seek = (loff_t)eb * mtd->eb_size; - ret = ioctl(fd, MEMSETBADBLOCK, &seek); - if (ret == -1) - return sys_errmsg("MEMSETBADBLOCK ioctl failed for " - "eraseblock %d (mtd%d)", eb, mtd->mtd_num); - return 0; -} - -int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs, - void *buf, int len) -{ - int ret, rd = 0; - off_t seek; - - if (eb < 0 || eb >= mtd->eb_cnt) { - errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", - eb, mtd->mtd_num, mtd->eb_cnt); - errno = EINVAL; - return -1; - } - if (offs < 0 || offs + len > mtd->eb_size) { - errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d", - offs, len, mtd->mtd_num, mtd->eb_size); - errno = EINVAL; - return -1; - } - - /* Seek to the beginning of the eraseblock */ - seek = (off_t)eb * mtd->eb_size + offs; - if (lseek(fd, seek, SEEK_SET) != seek) - return sys_errmsg("cannot seek mtd%d to offset %llu", - mtd->mtd_num, (unsigned long long)seek); - - while (rd < len) { - ret = read(fd, buf, len); - if (ret < 0) - return sys_errmsg("cannot read %d bytes from mtd%d (eraseblock %d, offset %d)", - len, mtd->mtd_num, eb, offs); - rd += ret; - } - - return 0; -} - -int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs, - void *buf, int len) -{ - int ret; - off_t seek; - - if (eb < 0 || eb >= mtd->eb_cnt) { - errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", - eb, mtd->mtd_num, mtd->eb_cnt); - errno = EINVAL; - return -1; - } - if (offs < 0 || offs + len > mtd->eb_size) { - errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d", - offs, len, mtd->mtd_num, mtd->eb_size); - errno = EINVAL; - return -1; - } - if (offs % mtd->subpage_size) { - errmsg("write offset %d is not aligned to mtd%d min. I/O size %d", - offs, mtd->mtd_num, mtd->subpage_size); - errno = EINVAL; - return -1; - } - if (len % mtd->subpage_size) { - errmsg("write length %d is not aligned to mtd%d min. I/O size %d", - len, mtd->mtd_num, mtd->subpage_size); - errno = EINVAL; - return -1; - } - - /* Seek to the beginning of the eraseblock */ - seek = (off_t)eb * mtd->eb_size + offs; - if (lseek(fd, seek, SEEK_SET) != seek) - return sys_errmsg("cannot seek mtd%d to offset %llu", - mtd->mtd_num, (unsigned long long)seek); - - ret = write(fd, buf, len); - if (ret != len) - return sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)", - len, mtd->mtd_num, eb, offs); - - return 0; -} - -int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs, - const char *img_name) -{ - int tmp, ret, in_fd, len, written = 0; - off_t seek; - struct stat st; - char *buf; - - if (eb < 0 || eb >= mtd->eb_cnt) { - errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks", - eb, mtd->mtd_num, mtd->eb_cnt); - errno = EINVAL; - return -1; - } - if (offs < 0 || offs >= mtd->eb_size) { - errmsg("bad offset %d, mtd%d eraseblock size is %d", - offs, mtd->mtd_num, mtd->eb_size); - errno = EINVAL; - return -1; - } - if (offs % mtd->subpage_size) { - errmsg("write offset %d is not aligned to mtd%d min. I/O size %d", - offs, mtd->mtd_num, mtd->subpage_size); - errno = EINVAL; - return -1; - } - - in_fd = open(img_name, O_RDONLY); - if (in_fd == -1) - return sys_errmsg("cannot open %s", img_name); - - if (fstat(in_fd, &st)) { - sys_errmsg("cannot stat %s", img_name); - goto out_close; - } - - len = st.st_size; - if (len % mtd->subpage_size) { - errmsg("size of \"%s\" is %d byte, which is not aligned to " - "mtd%d min. I/O size %d", img_name, len, mtd->mtd_num, - mtd->subpage_size); - errno = EINVAL; - goto out_close; - } - tmp = (offs + len + mtd->eb_size - 1) / mtd->eb_size; - if (eb + tmp > mtd->eb_cnt) { - errmsg("\"%s\" image size is %d bytes, mtd%d size is %d " - "eraseblocks, the image does not fit if we write it " - "starting from eraseblock %d, offset %d", - img_name, len, mtd->mtd_num, mtd->eb_cnt, eb, offs); - errno = EINVAL; - goto out_close; - } - - /* Seek to the beginning of the eraseblock */ - seek = (off_t)eb * mtd->eb_size + offs; - if (lseek(fd, seek, SEEK_SET) != seek) { - sys_errmsg("cannot seek mtd%d to offset %llu", - mtd->mtd_num, (unsigned long long)seek); - goto out_close; - } - - buf = malloc(mtd->eb_size); - if (!buf) { - sys_errmsg("cannot allocate %d bytes of memory", mtd->eb_size); - goto out_close; - } - - while (written < len) { - int rd = 0; - - do { - ret = read(in_fd, buf, mtd->eb_size - offs - rd); - if (ret == -1) { - sys_errmsg("cannot read from %s", img_name); - goto out_free; - } - rd += ret; - } while (ret && rd < mtd->eb_size - offs); - - ret = write(fd, buf, rd); - if (ret != rd) { - sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)", - len, mtd->mtd_num, eb, offs); - goto out_free; - } - - offs = 0; - eb += 1; - written += rd; - } - - free(buf); - close(in_fd); - return 0; - -out_free: - free(buf); -out_close: - close(in_fd); - return -1; -} - -int mtd_probe_node(libmtd_t desc, const char *node) -{ - struct stat st; - struct mtd_info info; - int i, major, minor; - struct libmtd *lib = (struct libmtd *)desc; - - 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 (mtd_get_info((libmtd_t *)lib, &info)) - return -1; - - if (!lib->sysfs_supported) - return 0; - - for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) { - int major1, minor1, ret; - - ret = dev_get_major(lib, i, &major1, &minor1); - if (ret) { - if (errno == ENOENT) - continue; - if (!errno) - break; - return -1; - } - - if (major1 == major && minor1 == minor) - return 1; - } - - errno = 0; - return -1; -} diff --git a/ubi-utils/src/libmtd_int.h b/ubi-utils/src/libmtd_int.h deleted file mode 100644 index 7de4b42..0000000 --- a/ubi-utils/src/libmtd_int.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * 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 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 - * - * MTD library. - */ - -#ifndef __LIBMTD_INT_H__ -#define __LIBMTD_INT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define PROGRAM_NAME "libmtd" - -#define SYSFS_MTD "class/mtd" -#define MTD_NAME_PATT "mtd%d" -#define MTD_DEV "dev" -#define MTD_NAME "name" -#define MTD_TYPE "type" -#define MTD_EB_SIZE "erasesize" -#define MTD_SIZE "size" -#define MTD_MIN_IO_SIZE "writesize" -#define MTD_SUBPAGE_SIZE "subpagesize" -#define MTD_OOB_SIZE "oobsize" -#define MTD_REGION_CNT "numeraseregions" -#define MTD_FLAGS "flags" - -/** - * libmtd - MTD library description data structure. - * @sysfs_mtd: MTD directory in sysfs - * @mtd: MTD device sysfs directory pattern - * @mtd_dev: MTD device major/minor numbers file pattern - * @mtd_name: MTD device name file pattern - * @mtd_type: MTD device type file pattern - * @mtd_eb_size: MTD device eraseblock size file pattern - * @mtd_size: MTD device size file pattern - * @mtd_min_io_size: minimum I/O unit size file pattern - * @mtd_subpage_size: sub-page size file pattern - * @mtd_oob_size: MTD device OOB size file pattern - * @mtd_region_cnt: count of additional erase regions file pattern - * @mtd_flags: MTD device flags file pattern - * @sysfs_supported: non-zero if sysfs is supported by MTD - */ -struct libmtd -{ - char *sysfs_mtd; - char *mtd; - char *mtd_dev; - char *mtd_name; - char *mtd_type; - char *mtd_eb_size; - char *mtd_size; - char *mtd_min_io_size; - char *mtd_subpage_size; - char *mtd_oob_size; - char *mtd_region_cnt; - char *mtd_flags; - unsigned int sysfs_supported:1; -}; - -int legacy_libmtd_open(void); -int legacy_mtd_get_info(struct mtd_info *info); -int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd); -int legacy_get_dev_info1(int dev_num, struct mtd_dev_info *mtd); - -#ifdef __cplusplus -} -#endif - -#endif /* !__LIBMTD_INT_H__ */ diff --git a/ubi-utils/src/libmtd_legacy.c b/ubi-utils/src/libmtd_legacy.c deleted file mode 100644 index 27fb3f8..0000000 --- a/ubi-utils/src/libmtd_legacy.c +++ /dev/null @@ -1,359 +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 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 - * - * This file is part of the MTD library. Implements pre-2.6.30 kernels support, - * where MTD did not have sysfs interface. The main limitation of the old - * kernels was that the sub-page size was not exported to user-space, so it was - * not possible to get sub-page size. - */ - -#include <limits.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <mtd/mtd-user.h> - -#include <libmtd.h> -#include "libmtd_int.h" -#include "common.h" - -#define MTD_PROC_FILE "/proc/mtd" -#define MTD_DEV_PATT "/dev/mtd%d" -#define MTD_DEV_MAJOR 90 - -#define PROC_MTD_FIRST "dev: size erasesize name\n" -#define PROC_MTD_FIRST_LEN (sizeof(PROC_MTD_FIRST) - 1) -#define PROC_MTD_MAX_LEN 4096 -#define PROC_MTD_PATT "mtd%d: %llx %x" - -/** - * struct proc_parse_info - /proc/mtd parsing information. - * @mtd_num: MTD device number - * @size: device size - * @eb_size: eraseblock size - * @name: device name - * @buf: contents of /proc/mtd - * @data_size: how much data was read into @buf - * @pos: next string in @buf to parse - */ -struct proc_parse_info -{ - int mtd_num; - long long size; - char name[MTD_NAME_MAX + 1]; - int eb_size; - char *buf; - int data_size; - char *next; -}; - -static int proc_parse_start(struct proc_parse_info *pi) -{ - int fd, ret; - - fd = open(MTD_PROC_FILE, O_RDONLY); - if (fd == -1) - return -1; - - pi->buf = malloc(PROC_MTD_MAX_LEN); - if (!pi->buf) { - sys_errmsg("cannot allocate %d bytes of memory", - PROC_MTD_MAX_LEN); - goto out_close; - } - - ret = read(fd, pi->buf, PROC_MTD_MAX_LEN); - if (ret == -1) { - sys_errmsg("cannot read \"%s\"", MTD_PROC_FILE); - goto out_free; - } - - if (ret < PROC_MTD_FIRST_LEN || - memcmp(pi->buf, PROC_MTD_FIRST, PROC_MTD_FIRST_LEN)) { - errmsg("\"%s\" does not start with \"%s\"", MTD_PROC_FILE, - PROC_MTD_FIRST); - goto out_free; - } - - pi->data_size = ret; - pi->next = pi->buf + PROC_MTD_FIRST_LEN; - - close(fd); - return 0; - -out_free: - free(pi->buf); -out_close: - close(fd); - return -1; -} - -static int proc_parse_next(struct proc_parse_info *pi) -{ - int ret, len, pos = pi->next - pi->buf; - char *p, *p1; - - if (pos >= pi->data_size) { - free(pi->buf); - return 0; - } - - ret = sscanf(pi->next, PROC_MTD_PATT, &pi->mtd_num, &pi->size, - &pi->eb_size); - if (ret != 3) - return errmsg("\"%s\" pattern not found", PROC_MTD_PATT); - - p = memchr(pi->next, '\"', pi->data_size - pos); - if (!p) - return errmsg("opening \" not fount"); - p += 1; - pos = p - pi->buf; - if (pos >= pi->data_size) - return errmsg("opening \" not fount"); - - p1 = memchr(p, '\"', pi->data_size - pos); - if (!p1) - return errmsg("closing \" not fount"); - pos = p1 - pi->buf; - if (pos >= pi->data_size) - return errmsg("closing \" not fount"); - - len = p1 - p; - if (len > MTD_NAME_MAX) - return errmsg("too long mtd%d device name", pi->mtd_num); - - memcpy(pi->name, p, len); - pi->name[len] = '\0'; - - if (p1[1] != '\n') - return errmsg("opening \"\n\" not fount"); - pi->next = p1 + 2; - return 1; -} - -/** - * legacy_libmtd_open - legacy version of 'libmtd_open()'. - * - * This function is just checks that MTD is present in the system. Returns - * zero in case of success and %-1 in case of failure. In case of failure, - * errno contains zero if MTD is not present in the system, or contains the - * error code if a real error happened. This is similar to the 'libmtd_open()' - * return conventions. - */ -int legacy_libmtd_open(void) -{ - int fd; - - fd = open(MTD_PROC_FILE, O_RDONLY); - if (fd == -1) { - if (errno == ENOENT) - errno = 0; - return -1; - } - - close(fd); - return 0; -} - -/** - * legacy_mtd_get_info - legacy version of 'mtd_get_info()'. - * @info: the MTD device information is returned here - * - * This function is similar to 'mtd_get_info()' and has the same conventions. - */ -int legacy_mtd_get_info(struct mtd_info *info) -{ - int ret; - struct proc_parse_info pi; - - ret = proc_parse_start(&pi); - if (ret) - return -1; - - info->lowest_mtd_num = INT_MAX; - while (proc_parse_next(&pi)) { - info->mtd_dev_cnt += 1; - if (pi.mtd_num > info->highest_mtd_num) - info->highest_mtd_num = pi.mtd_num; - if (pi.mtd_num < info->lowest_mtd_num) - info->lowest_mtd_num = pi.mtd_num; - } - - return 0; -} - -/** - * legacy_get_dev_info - legacy version of 'mtd_get_dev_info()'. - * @node: name of the MTD device node - * @mtd: the MTD device information is returned here - * - * This function is similar to 'mtd_get_dev_info()' and has the same - * conventions. - */ -int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd) -{ - struct stat st; - struct mtd_info_user ui; - int fd, ret; - loff_t offs = 0; - struct proc_parse_info pi; - - if (stat(node, &st)) { - sys_errmsg("cannot open \"%s\"", node); - if (errno == ENOENT) - normsg("MTD subsystem is old and does not support " - "sysfs, so MTD character device nodes have " - "to exist"); - } - - if (!S_ISCHR(st.st_mode)) { - errno = EINVAL; - return errmsg("\"%s\" is not a character device", node); - } - - memset(mtd, '\0', sizeof(struct mtd_dev_info)); - mtd->major = major(st.st_rdev); - mtd->minor = minor(st.st_rdev); - - if (mtd->major != MTD_DEV_MAJOR) { - errno = EINVAL; - return errmsg("\"%s\" has major number %d, MTD devices have " - "major %d", node, mtd->major, MTD_DEV_MAJOR); - } - - mtd->mtd_num = mtd->minor / 2; - - fd = open(node, O_RDWR); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - - if (ioctl(fd, MEMGETINFO, &ui)) { - sys_errmsg("MEMGETINFO ioctl request failed"); - goto out_close; - } - - ret = ioctl(fd, MEMGETBADBLOCK, &offs); - if (ret == -1) { - if (errno != EOPNOTSUPP) { - sys_errmsg("MEMGETBADBLOCK ioctl failed"); - goto out_close; - } - errno = 0; - mtd->bb_allowed = 0; - } else - mtd->bb_allowed = 1; - - mtd->type = ui.type; - mtd->size = ui.size; - mtd->eb_size = ui.erasesize; - mtd->min_io_size = ui.writesize; - - if (mtd->min_io_size <= 0) { - errmsg("mtd%d (%s) has insane min. I/O unit size %d", - mtd->mtd_num, node, mtd->min_io_size); - goto out_close; - } - if (mtd->eb_size <= 0 || mtd->eb_size < mtd->min_io_size) { - errmsg("mtd%d (%s) has insane eraseblock size %d", - mtd->mtd_num, node, mtd->eb_size); - goto out_close; - } - if (mtd->size <= 0 || mtd->size < mtd->eb_size) { - errmsg("mtd%d (%s) has insane size %lld", - mtd->mtd_num, node, mtd->size); - goto out_close; - } - mtd->eb_cnt = mtd->size / mtd->eb_size; - - switch(mtd->type) { - case MTD_ABSENT: - errmsg("mtd%d (%s) is removable and is not present", - mtd->mtd_num, node); - goto out_close; - case MTD_RAM: - strcpy((char *)mtd->type_str, "ram"); - break; - case MTD_ROM: - strcpy((char *)mtd->type_str, "rom"); - break; - case MTD_NORFLASH: - strcpy((char *)mtd->type_str, "nor"); - break; - case MTD_NANDFLASH: - strcpy((char *)mtd->type_str, "nand"); - break; - case MTD_DATAFLASH: - strcpy((char *)mtd->type_str, "dataflash"); - break; - case MTD_UBIVOLUME: - strcpy((char *)mtd->type_str, "ubi"); - break; - default: - goto out_close; - } - - if (ui.flags & MTD_WRITEABLE) - mtd->writable = 1; - mtd->subpage_size = mtd->min_io_size; - - close(fd); - - /* - * Unfortunately, the device name is not available via ioctl, and - * we have to parse /proc/mtd to get it. - */ - ret = proc_parse_start(&pi); - if (ret) - return -1; - - while (proc_parse_next(&pi)) { - if (pi.mtd_num == mtd->mtd_num) { - strcpy((char *)mtd->name, pi.name); - return 0; - } - } - - errmsg("mtd%d not found in \"%s\"", mtd->mtd_num, MTD_PROC_FILE); - errno = ENOENT; - return -1; - -out_close: - close(fd); - return -1; -} - -/** - * legacy_get_dev_info1 - legacy version of 'mtd_get_dev_info1()'. - * @node: name of the MTD device node - * @mtd: the MTD device information is returned here - * - * This function is similar to 'mtd_get_dev_info1()' and has the same - * conventions. - */ -int legacy_get_dev_info1(int mtd_num, struct mtd_dev_info *mtd) -{ - char node[sizeof(MTD_DEV_PATT) + 20]; - - sprintf(node, MTD_DEV_PATT, mtd_num); - return legacy_get_dev_info(node, mtd); -} diff --git a/ubi-utils/src/libscan.c b/ubi-utils/src/libscan.c index 5a2ea78..85f3d7f 100644 --- a/ubi-utils/src/libscan.c +++ b/ubi-utils/src/libscan.c @@ -32,8 +32,8 @@ #include <mtd/mtd-user.h> #include <libmtd.h> #include <libscan.h> +#include <crc32.h> #include "common.h" -#include "crc32.h" #define PROGRAM_NAME "libscan" diff --git a/ubi-utils/src/libubigen.c b/ubi-utils/src/libubigen.c index 8f060da..62792d0 100644 --- a/ubi-utils/src/libubigen.c +++ b/ubi-utils/src/libubigen.c @@ -32,7 +32,7 @@ #include <mtd/ubi-media.h> #include <mtd_swab.h> #include <libubigen.h> -#include "crc32.h" +#include <crc32.h> #include "common.h" #define PROGRAM_NAME "libubigen" diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/src/ubicrc32.c index d39af10..2dd69e1 100644 --- a/ubi-utils/src/ubicrc32.c +++ b/ubi-utils/src/ubicrc32.c @@ -28,8 +28,8 @@ #include <getopt.h> #include <unistd.h> #include <mtd/ubi-media.h> +#include <crc32.h> -#include "crc32.h" #include "common.h" #define BUFSIZE 4096 diff --git a/ubi-utils/src/ubiformat.c b/ubi-utils/src/ubiformat.c index 8487fd5..f0a87c4 100644 --- a/ubi-utils/src/ubiformat.c +++ b/ubi-utils/src/ubiformat.c @@ -41,7 +41,7 @@ #include <libscan.h> #include <libubigen.h> #include <mtd_swab.h> -#include "crc32.h" +#include <crc32.h> #include "common.h" #define PROGRAM_VERSION "1.5" |