X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/217eec334bc2a42184635c98afa27ff7b4aa7d8c..d7fc4ca3b44932e0ea0168ca6603b9f44cb78e34:/package/openwrt/mtd.c diff --git a/package/openwrt/mtd.c b/package/openwrt/mtd.c index ff104c657..f0c127b72 100644 --- a/package/openwrt/mtd.c +++ b/package/openwrt/mtd.c @@ -1,9 +1,8 @@ /* - * mtd.c + * mtd - simple memory technology device manipulation tool * - * Copyright (C) 2005 Waldemar Brodkorb - * - * $Id$ + * Copyright (C) 2005 Waldemar Brodkorb , + * Felix Fietkau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,10 +18,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * mtd utility for the openwrt project - * it is mainly code from the linux-mtd project, which accepts the same - * command line arguments as the broadcom utility - * + * $Id$ + * + * code is based on linux-mtd example code */ #include @@ -39,6 +37,7 @@ #include #include #include +#include #include #include @@ -49,6 +48,8 @@ #define TRX_MAX_LEN 0x3A0000 #define TRX_NO_HEADER 1 /* Do not write TRX header */ +#define MAX_ARGS 8 + struct trx_header { uint32_t magic; /* "HDR0" */ uint32_t len; /* Length of file including header */ @@ -59,9 +60,6 @@ struct trx_header { #define BUFSIZE (10 * 1024) -extern int mtd_open(const char *mtd, int flags); -extern int mtd_erase(const char *mtd); -extern int mtd_write(const char *trxfile, const char *mtd); int mtd_unlock(const char *mtd) @@ -82,12 +80,13 @@ mtd_unlock(const char *mtd) exit(1); } + printf("Unlocking %s ...\n", mtd); mtdLockInfo.start = 0; mtdLockInfo.length = mtdInfo.size; if(ioctl(fd, MEMUNLOCK, &mtdLockInfo)) { fprintf(stderr, "Could not unlock MTD device: %s\n", mtd); close(fd); - exit(1); + return 0; } close(fd); @@ -134,17 +133,14 @@ mtd_erase(const char *mtd) exit(1); } + printf("Erasing %s ...\n", mtd); mtdEraseInfo.length = mtdInfo.erasesize; for (mtdEraseInfo.start = 0; mtdEraseInfo.start < mtdInfo.size; mtdEraseInfo.start += mtdInfo.erasesize) { - if(ioctl(fd, MEMUNLOCK, &mtdEraseInfo)) { - fprintf(stderr, "Could not unlock MTD device: %s\n", mtd); - close(fd); - exit(1); - } + ioctl(fd, MEMUNLOCK, &mtdEraseInfo); if(ioctl(fd, MEMERASE, &mtdEraseInfo)) { fprintf(stderr, "Could not erase MTD device: %s\n", mtd); close(fd); @@ -194,18 +190,20 @@ mtd_write(const char *trxfile, const char *mtd) } if(mtdInfo.size < trxstat.st_size) { - fprintf(stderr, "image to big for mtd partition: %s\n", mtd); + fprintf(stderr, "Image too big for partition: %s\n", mtd); close(trxfd); exit(1); } + printf("Writing %s to %s ...\n", trxfile, mtd); + mtdEraseInfo.start = 0; mtdEraseInfo.length = trxstat.st_size & ~(mtdInfo.erasesize -1); if(trxstat.st_size % mtdInfo.erasesize) mtdEraseInfo.length += mtdInfo.erasesize; /* erase the chunk */ if (ioctl (fd,MEMERASE,&mtdEraseInfo) < 0) { - fprintf(stderr, "erasing mtd failed: %s\n", mtd); + fprintf(stderr, "Erasing mtd failed: %s\n", mtd); exit(1); } @@ -219,10 +217,10 @@ mtd_write(const char *trxfile, const char *mtd) result = write(fd,src,i); if (i != result) { if (result < 0) { - fprintf(stderr,"error while writing image"); + fprintf(stderr,"Error while writing image"); exit(1); } - fprintf(stderr,"error writing image"); + fprintf(stderr,"Error writing image"); exit(1); } written += i; @@ -232,21 +230,96 @@ mtd_write(const char *trxfile, const char *mtd) return 0; } -int main(int argc, char **argv) { - if(argc == 3 && strcasecmp(argv[1],"unlock")==0) { - printf("Unlocking %s\n",argv[2]); - return mtd_unlock(argv[2]); +void usage(void) +{ + printf("Usage: mtd [ ...] [ ...] \n\n" + "The device is in the format of mtdX (eg: mtd4) or its label.\n" + "mtd recognizes these commands:\n" + " unlock unlock the device\n" + " erase erase all data on device\n" + " write write imagefile to device\n" + "Following options are available:\n" + " -r reboot after successful command\n" + " -e erase before executing the command\n\n" + "Example: To write linux.trx to mtd4 labeled as linux and reboot afterwards\n" + " mtd -r write linux.trx linux\n\n"); + exit(1); +} + +int main (int argc, char **argv) +{ + int ch, i, boot, unlock; + char *erase[MAX_ARGS], *device; + enum { + CMD_ERASE, + CMD_WRITE, + CMD_UNLOCK + } cmd; + + erase[0] = NULL; + boot = 0; + + while ((ch = getopt(argc, argv, "re:")) != -1) + switch (ch) { + case 'r': + boot = 1; + break; + case 'e': + i = 0; + while ((erase[i] != NULL) && ((i + 1) < MAX_ARGS)) + i++; + + erase[i++] = optarg; + erase[i] = NULL; + break; + + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc < 2) + usage(); + + if ((strcmp(argv[0], "unlock") == 0) && (argc == 2)) { + cmd = CMD_UNLOCK; + device = argv[1]; + } else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) { + cmd = CMD_ERASE; + device = argv[1]; + } else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) { + cmd = CMD_WRITE; + device = argv[2]; + } else { + usage(); } - if(argc == 3 && strcasecmp(argv[1],"erase")==0) { - printf("Erasing %s\n",argv[2]); - return mtd_erase(argv[2]); + + sync(); + + i = 0; + while (erase[i] != NULL) { + mtd_unlock(erase[i]); + mtd_erase(erase[i]); + i++; } - if(argc == 4 && strcasecmp(argv[1],"write")==0) { - printf("Writing %s to %s\n",argv[2],argv[3]); - return mtd_write(argv[2],argv[3]); + + mtd_unlock(device); + + switch (cmd) { + case CMD_UNLOCK: + break; + case CMD_ERASE: + mtd_erase(device); + break; + case CMD_WRITE: + mtd_write(argv[1], device); + break; } - printf("no valid command given\n"); - return -1; -} + if (boot) + kill(1, 15); // send SIGTERM to init for reboot + return 0; +}