diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2009-12-17 17:36:04 +0100 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2009-12-17 17:36:04 +0100 |
commit | bb17a19fcc7f7d10369eed7f6c8662f6e4df9d4b (patch) | |
tree | acd8cde7844e2039275049a769461e640afff9ca /package/mtd | |
parent | 11a25b78e7c010ed5f2b60fc85a5ac952a4c0e73 (diff) |
enable cfgfs and atm
- make cfgfs work for ag241
- split mtd to separate package to control dependencies
- update linux-atm package to latest upstream
- enable atm kernel module building
Diffstat (limited to 'package/mtd')
-rw-r--r-- | package/mtd/Config.in | 9 | ||||
-rw-r--r-- | package/mtd/Makefile | 32 | ||||
-rw-r--r-- | package/mtd/src/mtd.c | 379 |
3 files changed, 420 insertions, 0 deletions
diff --git a/package/mtd/Config.in b/package/mtd/Config.in new file mode 100644 index 000000000..aacc297b5 --- /dev/null +++ b/package/mtd/Config.in @@ -0,0 +1,9 @@ +config ADK_PACKAGE_MTD + prompt "mtd................................ mtd utility" + tristate + depends on \ + ADK_LINUX_CRIS_FOXBOARD || \ + ADK_LINUX_MIPS_AG241 + default n + help + MTD utility. diff --git a/package/mtd/Makefile b/package/mtd/Makefile new file mode 100644 index 000000000..67aa1f30c --- /dev/null +++ b/package/mtd/Makefile @@ -0,0 +1,32 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include ${TOPDIR}/rules.mk + +PKG_NAME:= mtd +PKG_VERSION:= 1.0 +PKG_RELEASE:= 1 +PKG_DESCR:= MTD utility +PKG_SECTION:= base + +WRKDIST= ${WRKDIR}/${PKG_NAME}-${PKG_VERSION} +NO_DISTFILES:= 1 + +include ${TOPDIR}/mk/package.mk + +$(eval $(call PKG_template,MTD,${PKG_NAME},${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +BUILD_STYLE:= manual +INSTALL_STYLE:= manual + +do-build: + mkdir -p ${WRKBUILD} + ${CP} ./src/* ${WRKBUILD} + ${TARGET_CC} ${TCPPFLAGS} ${TCFLAGS} -o ${WRKBUILD}/mtd \ + ${WRKBUILD}/mtd.c + +do-install: + ${INSTALL_DIR} ${IDIR_MTD}/sbin + ${INSTALL_BIN} ${WRKBUILD}/mtd ${IDIR_MTD}/sbin/mtd + +include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/mtd/src/mtd.c b/package/mtd/src/mtd.c new file mode 100644 index 000000000..6812c5e31 --- /dev/null +++ b/package/mtd/src/mtd.c @@ -0,0 +1,379 @@ +/* + * mtd - simple memory technology device manipulation tool + * + * Copyright (c) 2006, 2007 Thorsten Glaser <tg@freewrt.org> + * Copyright (C) 2005 Waldemar Brodkorb <wbx@freewrt.org>, + * Felix Fietkau <nbd@openwrt.org> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The code is based on the linux-mtd examples. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/syscall.h> +#include <limits.h> +#include <unistd.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <error.h> +#include <err.h> +#include <time.h> +#include <string.h> + +#include <mtd/mtd-user.h> + +#define BUFSIZE (16 * 1024) +#define MAX_ARGS 8 + +#define DEBUG + +int mtd_check(char *); +int mtd_unlock(const char *); +int mtd_open(const char *, int); +int mtd_erase(const char *); +int mtd_write(int, const char *, int, bool); +void usage(void) __attribute__((noreturn)); + +char buf[BUFSIZE]; +int buflen; + +int +mtd_check(char *mtd) +{ + struct mtd_info_user mtdInfo; + int fd; + + fd = mtd_open(mtd, O_RDWR | O_SYNC); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + return 0; + } + + if(ioctl(fd, MEMGETINFO, &mtdInfo)) { + fprintf(stderr, "Could not get MTD device info from %s\n", mtd); + close(fd); + return 0; + } + + close(fd); + return 1; +} + +int +mtd_unlock(const char *mtd) +{ + int fd; + struct mtd_info_user mtdInfo; + struct erase_info_user mtdLockInfo; + + fd = mtd_open(mtd, O_RDWR | O_SYNC); + 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); + } + + mtdLockInfo.start = 0; + mtdLockInfo.length = mtdInfo.size; + if(ioctl(fd, MEMUNLOCK, &mtdLockInfo)) { + close(fd); + return 0; + } + + close(fd); + return 0; +} + +int +mtd_open(const char *mtd, int flags) +{ + FILE *fp; + char dev[PATH_MAX]; + int i; + + if ((fp = fopen("/proc/mtd", "r"))) { + while (fgets(dev, sizeof(dev), fp)) { + if (sscanf(dev, "mtd%d:", &i) && strstr(dev, mtd)) { + snprintf(dev, sizeof(dev), "/dev/mtd%d", i); + fclose(fp); + return open(dev, flags); + } + } + fclose(fp); + } + + return open(mtd, flags); +} + +int +mtd_erase(const char *mtd) +{ + int fd; + struct mtd_info_user mtdInfo; + struct erase_info_user mtdEraseInfo; + + fd = mtd_open(mtd, O_RDWR | O_SYNC); + 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); + } + + mtdEraseInfo.length = mtdInfo.erasesize; + + for (mtdEraseInfo.start = 0; + mtdEraseInfo.start < mtdInfo.size; + mtdEraseInfo.start += mtdInfo.erasesize) { + + ioctl(fd, MEMUNLOCK, &mtdEraseInfo); + if(ioctl(fd, MEMERASE, &mtdEraseInfo)) { + fprintf(stderr, "Could not erase MTD device: %s\n", mtd); + close(fd); + exit(1); + } + } + + close(fd); + return 0; + +} + +int +mtd_write(int imagefd, const char *mtd, int quiet, bool do_erase) +{ + int fd, result; + size_t r, w, e; + struct mtd_info_user mtdInfo; + struct erase_info_user mtdEraseInfo; + + fd = mtd_open(mtd, O_RDWR | O_SYNC); + 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); + } + + r = w = e = 0; + if (!quiet) + fprintf(stderr, " [ ]"); + + for (;;) { + /* buffer may contain data already (from trx check) */ + r = buflen; + r += read(imagefd, buf + buflen, BUFSIZE - buflen); + w += r; + + /* EOF */ + if (r <= 0) break; + + /* need to erase the next block before writing data to it */ + while (do_erase && w > e) { + mtdEraseInfo.start = e; + mtdEraseInfo.length = mtdInfo.erasesize; + + if (!quiet) + fprintf(stderr, "\b\b\b[e]"); + /* erase the chunk */ + if (ioctl (fd,MEMERASE,&mtdEraseInfo) < 0) { + fprintf(stderr, "Erasing mtd failed: %s\n", mtd); + exit(1); + } + e += mtdInfo.erasesize; + } + + if (!quiet) + fprintf(stderr, "\b\b\b[w]"); + + if ((result = write(fd, buf, r)) < (ssize_t)r) { + if (result < 0) { + fprintf(stderr, "Error writing image.\n"); + exit(1); + } else { + fprintf(stderr, "Insufficient space.\n"); + exit(1); + } + } + + buflen = 0; + } + if (!quiet) + fprintf(stderr, "\b\b\b\b"); + + close(fd); + return 0; +} + +void +usage(void) +{ + fprintf(stderr, "Usage: mtd [<options> ...] <command> [<arguments> ...] <device>\n\n" + "The device is in the format of mtdX (eg: mtd4) or its label.\n" + "mtd recognises these commands:\n" + " unlock unlock the device\n" + " erase erase all data on device\n" + " write <imagefile>|- write <imagefile> (use - for stdin) to device\n" + "Following options are available:\n" + " -q quiet mode (once: no [w] on writing,\n" + " twice: no status messages)\n" + " -e <device> erase <device> before executing the command\n\n" + "Example: To write linux.trx to mtd1 labeled as linux\n" + " mtd write linux.trx linux\n\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int ch, i, imagefd = -1, quiet, unlocked; + char *erase[MAX_ARGS], *device; + const char *imagefile = NULL; + enum { + CMD_ERASE, + CMD_WRITE, + CMD_UNLOCK + } cmd; + + erase[0] = NULL; + buflen = 0; + quiet = 0; + + while ((ch = getopt(argc, argv, "Fqe:")) != -1) + switch (ch) { + case 'F': + quiet = 1; + /* FALLTHROUGH */ + case 'q': + quiet++; + 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]; + + if (strcmp(argv[1], "-") == 0) { + imagefile = "<stdin>"; + imagefd = 0; + } else { + imagefile = argv[1]; + if ((imagefd = open(argv[1], O_RDONLY)) < 0) { + fprintf(stderr, "Couldn't open image file: %s!\n", imagefile); + exit(1); + } + } + + if (!mtd_check(device)) { + fprintf(stderr, "Can't open device for writing!\n"); + exit(1); + } + } else { + usage(); + } + + sync(); + + i = 0; + unlocked = 0; + while (erase[i] != NULL) { + if (quiet < 2) + fprintf(stderr, "Unlocking %s ...\n", erase[i]); + mtd_unlock(erase[i]); + if (quiet < 2) + fprintf(stderr, "Erasing %s ...\n", erase[i]); + mtd_erase(erase[i]); + if (strcmp(erase[i], device) == 0) + /* this means that <device> is unlocked and erased */ + unlocked = 1; + i++; + } + + if (!unlocked) { + if (quiet < 2) + fprintf(stderr, "Unlocking %s ...\n", device); + mtd_unlock(device); + } + + switch (cmd) { + case CMD_UNLOCK: + break; + case CMD_ERASE: + if (unlocked) { + fprintf(stderr, "Already erased: %s\n", device); + break; + } + if (quiet < 2) + fprintf(stderr, "Erasing %s ...\n", device); + mtd_erase(device); + break; + case CMD_WRITE: + if (quiet < 2) + fprintf(stderr, "Writing from %s to %s ... ", imagefile, device); + mtd_write(imagefd, device, quiet, (unlocked == 0)); + if (quiet < 2) + fprintf(stderr, "\n"); + break; + } + + sync(); + return 0; +} |