diff options
Diffstat (limited to 'flashcp.c')
-rw-r--r-- | flashcp.c | 389 |
1 files changed, 0 insertions, 389 deletions
diff --git a/flashcp.c b/flashcp.c deleted file mode 100644 index 86334ac..0000000 --- a/flashcp.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2d3D, Inc. - * Written by Abraham vd Merwe <abraham@2d3d.co.za> - * All rights reserved. - * - * Renamed to flashcp.c to avoid conflicts with fcp from fsh package - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of other contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define PROGRAM_NAME "flashcp" - -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <unistd.h> -#include <mtd/mtd-user.h> -#include <getopt.h> - -typedef int bool; -#define true 1 -#define false 0 - -#define EXIT_FAILURE 1 -#define EXIT_SUCCESS 0 - -/* for debugging purposes only */ -#ifdef DEBUG -#undef DEBUG -#define DEBUG(fmt,args...) { log_printf (LOG_ERROR,"%d: ",__LINE__); log_printf (LOG_ERROR,fmt,## args); } -#else -#undef DEBUG -#define DEBUG(fmt,args...) -#endif - -#define KB(x) ((x) / 1024) -#define PERCENTAGE(x,total) (((x) * 100) / (total)) - -/* size of read/write buffer */ -#define BUFSIZE (10 * 1024) - -/* cmd-line flags */ -#define FLAG_NONE 0x00 -#define FLAG_VERBOSE 0x01 -#define FLAG_HELP 0x02 -#define FLAG_FILENAME 0x04 -#define FLAG_DEVICE 0x08 - -/* error levels */ -#define LOG_NORMAL 1 -#define LOG_ERROR 2 - -static void log_printf (int level,const char *fmt, ...) -{ - FILE *fp = level == LOG_NORMAL ? stdout : stderr; - va_list ap; - va_start (ap,fmt); - vfprintf (fp,fmt,ap); - va_end (ap); - fflush (fp); -} - -static void showusage(bool error) -{ - int level = error ? LOG_ERROR : LOG_NORMAL; - - log_printf (level, - "\n" - "Flash Copy - Written by Abraham van der Merwe <abraham@2d3d.co.za>\n" - "\n" - "usage: %1$s [ -v | --verbose ] <filename> <device>\n" - " %1$s -h | --help\n" - "\n" - " -h | --help Show this help message\n" - " -v | --verbose Show progress reports\n" - " <filename> File which you want to copy to flash\n" - " <device> Flash device to write to (e.g. /dev/mtd0, /dev/mtd1, etc.)\n" - "\n", - PROGRAM_NAME); - - exit (error ? EXIT_FAILURE : EXIT_SUCCESS); -} - -static int safe_open (const char *pathname,int flags) -{ - int fd; - - fd = open (pathname,flags); - if (fd < 0) - { - log_printf (LOG_ERROR,"While trying to open %s",pathname); - if (flags & O_RDWR) - log_printf (LOG_ERROR," for read/write access"); - else if (flags & O_RDONLY) - log_printf (LOG_ERROR," for read access"); - else if (flags & O_WRONLY) - log_printf (LOG_ERROR," for write access"); - log_printf (LOG_ERROR,": %m\n"); - exit (EXIT_FAILURE); - } - - return (fd); -} - -static void safe_read (int fd,const char *filename,void *buf,size_t count,bool verbose) -{ - ssize_t result; - - result = read (fd,buf,count); - if (count != result) - { - if (verbose) log_printf (LOG_NORMAL,"\n"); - if (result < 0) - { - log_printf (LOG_ERROR,"While reading data from %s: %m\n",filename); - exit (EXIT_FAILURE); - } - log_printf (LOG_ERROR,"Short read count returned while reading from %s\n",filename); - exit (EXIT_FAILURE); - } -} - -static void safe_rewind (int fd,const char *filename) -{ - if (lseek (fd,0L,SEEK_SET) < 0) - { - log_printf (LOG_ERROR,"While seeking to start of %s: %m\n",filename); - exit (EXIT_FAILURE); - } -} - -/******************************************************************************/ - -static int dev_fd = -1,fil_fd = -1; - -static void cleanup (void) -{ - if (dev_fd > 0) close (dev_fd); - if (fil_fd > 0) close (fil_fd); -} - -int main (int argc,char *argv[]) -{ - const char *filename = NULL,*device = NULL; - int i,flags = FLAG_NONE; - ssize_t result; - size_t size,written; - struct mtd_info_user mtd; - struct erase_info_user erase; - struct stat filestat; - unsigned char src[BUFSIZE],dest[BUFSIZE]; - - /********************* - * parse cmd-line - *****************/ - - for (;;) { - int option_index = 0; - static const char *short_options = "hv"; - static const struct option long_options[] = { - {"help", no_argument, 0, 'h'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0}, - }; - - int c = getopt_long(argc, argv, short_options, - long_options, &option_index); - if (c == EOF) { - break; - } - - switch (c) { - case 'h': - flags |= FLAG_HELP; - DEBUG("Got FLAG_HELP\n"); - break; - case 'v': - flags |= FLAG_VERBOSE; - DEBUG("Got FLAG_VERBOSE\n"); - break; - default: - DEBUG("Unknown parameter: %s\n",argv[option_index]); - showusage(true); - } - } - if (optind+2 == argc) { - flags |= FLAG_FILENAME; - filename = argv[optind]; - DEBUG("Got filename: %s\n",filename); - - flags |= FLAG_DEVICE; - device = argv[optind+1]; - DEBUG("Got device: %s\n",device); - } - - if (flags & FLAG_HELP || device == NULL) - showusage(flags != FLAG_HELP); - - atexit (cleanup); - - /* get some info about the flash device */ - dev_fd = safe_open (device,O_SYNC | O_RDWR); - if (ioctl (dev_fd,MEMGETINFO,&mtd) < 0) - { - DEBUG("ioctl(): %m\n"); - log_printf (LOG_ERROR,"This doesn't seem to be a valid MTD flash device!\n"); - exit (EXIT_FAILURE); - } - - /* get some info about the file we want to copy */ - fil_fd = safe_open (filename,O_RDONLY); - if (fstat (fil_fd,&filestat) < 0) - { - log_printf (LOG_ERROR,"While trying to get the file status of %s: %m\n",filename); - exit (EXIT_FAILURE); - } - - /* does it fit into the device/partition? */ - if (filestat.st_size > mtd.size) - { - log_printf (LOG_ERROR,"%s won't fit into %s!\n",filename,device); - exit (EXIT_FAILURE); - } - - /***************************************************** - * erase enough blocks so that we can write the file * - *****************************************************/ - -#warning "Check for smaller erase regions" - - erase.start = 0; - erase.length = (filestat.st_size + mtd.erasesize - 1) / mtd.erasesize; - erase.length *= mtd.erasesize; - - if (flags & FLAG_VERBOSE) - { - /* if the user wants verbose output, erase 1 block at a time and show him/her what's going on */ - int blocks = erase.length / mtd.erasesize; - erase.length = mtd.erasesize; - log_printf (LOG_NORMAL,"Erasing blocks: 0/%d (0%%)",blocks); - for (i = 1; i <= blocks; i++) - { - log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d (%d%%)",i,blocks,PERCENTAGE (i,blocks)); - if (ioctl (dev_fd,MEMERASE,&erase) < 0) - { - log_printf (LOG_NORMAL,"\n"); - log_printf (LOG_ERROR, - "While erasing blocks 0x%.8x-0x%.8x on %s: %m\n", - (unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device); - exit (EXIT_FAILURE); - } - erase.start += mtd.erasesize; - } - log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d (100%%)\n",blocks,blocks); - } - else - { - /* if not, erase the whole chunk in one shot */ - if (ioctl (dev_fd,MEMERASE,&erase) < 0) - { - log_printf (LOG_ERROR, - "While erasing blocks from 0x%.8x-0x%.8x on %s: %m\n", - (unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device); - exit (EXIT_FAILURE); - } - } - DEBUG("Erased %u / %luk bytes\n",erase.length,filestat.st_size); - - /********************************** - * write the entire file to flash * - **********************************/ - - if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"Writing data: 0k/%luk (0%%)",KB (filestat.st_size)); - size = filestat.st_size; - i = BUFSIZE; - written = 0; - while (size) - { - if (size < BUFSIZE) i = size; - if (flags & FLAG_VERBOSE) - log_printf (LOG_NORMAL,"\rWriting data: %dk/%luk (%lu%%)", - KB (written + i), - KB (filestat.st_size), - PERCENTAGE (written + i,filestat.st_size)); - - /* read from filename */ - safe_read (fil_fd,filename,src,i,flags & FLAG_VERBOSE); - - /* write to device */ - result = write (dev_fd,src,i); - if (i != result) - { - if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"\n"); - if (result < 0) - { - log_printf (LOG_ERROR, - "While writing data to 0x%.8x-0x%.8x on %s: %m\n", - written,written + i,device); - exit (EXIT_FAILURE); - } - log_printf (LOG_ERROR, - "Short write count returned while writing to x%.8x-0x%.8x on %s: %d/%lu bytes written to flash\n", - written,written + i,device,written + result,filestat.st_size); - exit (EXIT_FAILURE); - } - - written += i; - size -= i; - } - if (flags & FLAG_VERBOSE) - log_printf (LOG_NORMAL, - "\rWriting data: %luk/%luk (100%%)\n", - KB (filestat.st_size), - KB (filestat.st_size)); - DEBUG("Wrote %d / %luk bytes\n",written,filestat.st_size); - - /********************************** - * verify that flash == file data * - **********************************/ - - safe_rewind (fil_fd,filename); - safe_rewind (dev_fd,device); - size = filestat.st_size; - i = BUFSIZE; - written = 0; - if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"Verifying data: 0k/%luk (0%%)",KB (filestat.st_size)); - while (size) - { - if (size < BUFSIZE) i = size; - if (flags & FLAG_VERBOSE) - log_printf (LOG_NORMAL, - "\rVerifying data: %dk/%luk (%lu%%)", - KB (written + i), - KB (filestat.st_size), - PERCENTAGE (written + i,filestat.st_size)); - - /* read from filename */ - safe_read (fil_fd,filename,src,i,flags & FLAG_VERBOSE); - - /* read from device */ - safe_read (dev_fd,device,dest,i,flags & FLAG_VERBOSE); - - /* compare buffers */ - if (memcmp (src,dest,i)) - { - log_printf (LOG_ERROR, - "File does not seem to match flash data. First mismatch at 0x%.8x-0x%.8x\n", - written,written + i); - exit (EXIT_FAILURE); - } - - written += i; - size -= i; - } - if (flags & FLAG_VERBOSE) - log_printf (LOG_NORMAL, - "\rVerifying data: %luk/%luk (100%%)\n", - KB (filestat.st_size), - KB (filestat.st_size)); - DEBUG("Verified %d / %luk bytes\n",written,filestat.st_size); - - exit (EXIT_SUCCESS); -} |