X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/8b28b2a559e0fe89fd86dec1ea5a8be00a16b499..931c7341682d90f58b6f918be57e10283b4e2072:/package/openwrt/mtd.c diff --git a/package/openwrt/mtd.c b/package/openwrt/mtd.c index 528eef3c2..74949fdac 100644 --- a/package/openwrt/mtd.c +++ b/package/openwrt/mtd.c @@ -1,7 +1,8 @@ /* * mtd - simple memory technology device manipulation tool * - * Copyright (C) 2005 Waldemar Brodkorb + * 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 @@ -17,12 +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,29 +37,89 @@ #include #include #include +#include #include #include -/* trx header */ #define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 -#define TRX_MAX_LEN 0x3A0000 -#define TRX_NO_HEADER 1 /* Do not write TRX header */ +#define BUFSIZE (10 * 1024) +#define MAX_ARGS 8 struct trx_header { - uint32_t magic; /* "HDR0" */ - uint32_t len; /* Length of file including header */ - uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ - uint32_t flag_version; /* 0:15 flags, 16:31 version */ + uint32_t magic; /* "HDR0" */ + uint32_t len; /* Length of file including header */ + uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ + uint32_t flag_version; /* 0:15 flags, 16:31 version */ uint32_t offsets[3]; /* Offsets of partitions from start of header */ }; -#define BUFSIZE (10 * 1024) +int +trx_check(const char *trxfile, const char *mtd) +{ + struct mtd_info_user mtdInfo; + int trxfd, fd; + size_t count; + struct trx_header trx; + struct stat trxstat; + + trxfd = open(trxfile,O_RDONLY); + if(trxfd < 0) { + fprintf(stderr, "Could not open trx image: %s\n", trxfile); + exit(1); + } + + if (fstat(trxfd,&trxstat) < 0) { + fprintf(stderr, "Could not get trx image file status: %s\n", trxfile); + close(trxfd); + exit(1); + } + + count = read(trxfd, &trx, sizeof(struct trx_header)); + if (count < sizeof(struct trx_header)) { + fprintf(stderr, "Could not trx header, file too small (%ld bytes)\n", count); + close(trxfd); + exit(1); + } + + if (trx.magic != TRX_MAGIC || trx.len < sizeof(struct trx_header)) { + fprintf(stderr, "Bad trx header\n"); + fprintf(stderr, "If this is a firmware in bin format, like some of the\n" + "original firmware files are, use following command to convert to trx:\n" + "dd if=firmware.bin of=firmware.trx bs=32 skip=1\n"); + close(trxfd); + exit(1); + } + + lseek(trxfd, 0, SEEK_SET); + + /* check if image fits to mtd device */ + + fd = mtd_open(mtd, O_RDWR); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + exit(1); + } + + if(ioctl(fd, MEMGETINFO, &mtdInfo)) { + fprintf(stderr, "Could not get MTD device info from %s\n", mtd); + close(fd); + exit(1); + } + + if(mtdInfo.size < trxstat.st_size) { + fprintf(stderr, "Image too big for partition: %s\n", mtd); + close(trxfd); + close(fd); + exit(1); + } + + printf("Writing %s to %s ...\n", trxfile, mtd); + + close(fd); -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); + return(trxfd); +} int mtd_unlock(const char *mtd) @@ -82,12 +140,12 @@ 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,6 +192,7 @@ mtd_erase(const char *mtd) exit(1); } + printf("Erasing %s ...\n", mtd); mtdEraseInfo.length = mtdInfo.erasesize; for (mtdEraseInfo.start = 0; @@ -154,16 +213,20 @@ mtd_erase(const char *mtd) } int -mtd_write(const char *trxfile, const char *mtd) +mtd_write(int trxfd, const char *mtd) { - int fd; - int trxfd; - int i; + int fd,i; size_t result,size,written; struct mtd_info_user mtdInfo; struct erase_info_user mtdEraseInfo; - struct stat trxstat; unsigned char src[BUFSIZE],dest[BUFSIZE]; + struct stat trxstat; + + if (fstat(trxfd,&trxstat) < 0) { + fprintf(stderr, "Could not get trx image file status\n"); + close(trxfd); + exit(1); + } fd = mtd_open(mtd, O_RDWR); if(fd < 0) { @@ -176,25 +239,7 @@ mtd_write(const char *trxfile, const char *mtd) close(fd); exit(1); } - - trxfd = open(trxfile,O_RDONLY); - if(trxfd < 0) { - fprintf(stderr, "Could not open trx image: %s\n", trxfile); - exit(1); - } - - if (fstat (trxfd,&trxstat) < 0) { - fprintf(stderr, "Could not get trx image file status: %s\n", trxfile); - close(trxfd); - exit(1); - } - if(mtdInfo.size < trxstat.st_size) { - fprintf(stderr, "Image too big for partition: %s\n", mtd); - close(trxfd); - exit(1); - } - mtdEraseInfo.start = 0; mtdEraseInfo.length = trxstat.st_size & ~(mtdInfo.erasesize -1); if(trxstat.st_size % mtdInfo.erasesize) mtdEraseInfo.length += mtdInfo.erasesize; @@ -228,33 +273,98 @@ 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, trxfd; + 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]; + /* check trx file before erasing or writing anything */ + trxfd = trx_check(argv[1], device); + } 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(trxfd, device); + break; } - printf("no valid command given\n"); - printf("\nmtd: modify data within a Memory Technology Device.\n"); - printf("Copyright (C) 2005 Waldemar Brodkorb \n"); - printf("Documented by Mike Strates [dumpedcore] \n"); - printf("mtd has ABSOLUTELY NO WARRANTY and is licensed under the GNU GPL.\n"); - printf("\nUsage: mtd [unlock|erase] device\n"); - printf(" mtd write imagefile device\n"); - printf("\n .. where device is in the format of mtdX (eg: mtd4) or its label.\n"); - printf("\nunlock enable modification to device\n"); - printf("erase erase all data on device\n"); - printf("write write imagefile to device\n"); - printf("\nExample: To write linux.trx to mtd4 labeled as linux\n"); - printf("\n mtd unlock linux && mtd write linux.trx linux\n\n"); - return -1; -} + if (boot) + kill(1, 15); // send SIGTERM to init for reboot + return 0; +}