aboutsummaryrefslogtreecommitdiff
path: root/misc-utils
diff options
context:
space:
mode:
Diffstat (limited to 'misc-utils')
-rw-r--r--misc-utils/Makemodule.am48
-rw-r--r--misc-utils/fectest.c4
-rw-r--r--misc-utils/flash_erase.c130
-rw-r--r--misc-utils/flash_otp_dump.c2
-rw-r--r--misc-utils/flash_otp_erase.c64
-rw-r--r--misc-utils/flash_unlock.c9
-rw-r--r--misc-utils/flashcp.c367
-rw-r--r--misc-utils/lsmtd.82
-rw-r--r--misc-utils/lsmtd.c6
-rw-r--r--misc-utils/lsmtd_scan.c2
-rw-r--r--misc-utils/mtd_debug.c7
-rw-r--r--misc-utils/mtdpart.c9
12 files changed, 464 insertions, 186 deletions
diff --git a/misc-utils/Makemodule.am b/misc-utils/Makemodule.am
index 2289252..1ce1a68 100644
--- a/misc-utils/Makemodule.am
+++ b/misc-utils/Makemodule.am
@@ -1,24 +1,34 @@
-ftl_format_SOURCES = misc-utils/ftl_format.c
+ftl_format_SOURCES = misc-utils/ftl_format.c include/mtd_swab.h
+ftl_format_SOURCES += include/mtd/ftl-user.h
doc_loadbios_SOURCES = misc-utils/doc_loadbios.c
-ftl_check_SOURCES = misc-utils/ftl_check.c
+ftl_check_SOURCES = misc-utils/ftl_check.c include/mtd_swab.h
+ftl_check_SOURCES += include/mtd/ftl-user.h
mtd_debug_SOURCES = misc-utils/mtd_debug.c
+mtd_debug_LDADD = libmtd.a
mtdpart_SOURCES = misc-utils/mtdpart.c
+mtdpart_LDADD = libmtd.a
-docfdisk_SOURCES = misc-utils/docfdisk.c
+docfdisk_SOURCES = misc-utils/docfdisk.c include/mtd_swab.h
+docfdisk_SOURCES += include/mtd/inftl-user.h include/mtd/ftl-user.h
-serve_image_SOURCES = misc-utils/serve_image.c
+serve_image_SOURCES = misc-utils/serve_image.c misc-utils/mcast_image.h
serve_image_LDADD = libmtd.a
-recv_image_SOURCES = misc-utils/recv_image.c
+recv_image_SOURCES = misc-utils/recv_image.c misc-utils/mcast_image.h
recv_image_LDADD = libmtd.a
+fectest_SOURCES = misc-utils/fectest.c misc-utils/mcast_image.h
+fectest_LDADD = libmtd.a
+
flash_lock_SOURCES = misc-utils/flash_lock.c
+flash_lock_LDADD = libmtd.a
flash_unlock_SOURCES = misc-utils/flash_unlock.c
+flash_unlock_LDADD = libmtd.a
flash_otp_info_SOURCES = misc-utils/flash_otp_info.c
@@ -26,42 +36,34 @@ flash_otp_dump_SOURCES = misc-utils/flash_otp_dump.c
flash_otp_lock_SOURCES = misc-utils/flash_otp_lock.c
+flash_otp_erase_SOURCES = misc-utils/flash_otp_erase.c
+
flash_otp_write_SOURCES = misc-utils/flash_otp_write.c
flashcp_SOURCES = misc-utils/flashcp.c
+flashcp_LDADD = libmtd.a
flash_erase_SOURCES = misc-utils/flash_erase.c
flash_erase_LDADD = libmtd.a
-MISC_BINS = \
+sbin_PROGRAMS += \
ftl_format doc_loadbios ftl_check mtd_debug docfdisk \
- serve_image recv_image flash_erase flash_lock \
+ serve_image recv_image fectest flash_erase flash_lock \
flash_unlock flash_otp_info flash_otp_dump flash_otp_lock \
- flash_otp_write flashcp mtdpart
+ flash_otp_erase flash_otp_write flashcp mtdpart
MISC_SH = \
misc-utils/flash_eraseall
-MISC_EXTRA = \
- misc-utils/MAKEDEV
-
-MISC_HEADER = \
- misc-utils/mcast_image.h \
- misc-utils/lsmtd.h
-
-MISC_MAN =
-
if BUILD_LSMTD
-lsmtd_SOURCES = misc-utils/lsmtd.c misc-utils/lsmtd_scan.c
+lsmtd_SOURCES = misc-utils/lsmtd.c misc-utils/lsmtd_scan.c misc-utils/lsmtd.h
lsmtd_LDADD = libmtd.a libubi.a
lsmtd_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/misc-utils
-MISC_BINS += lsmtd
-MISC_MAN += misc-utils/lsmtd.8
+sbin_PROGRAMS += lsmtd
+dist_man8_MANS += misc-utils/lsmtd.8
endif
-EXTRA_DIST += $(MISC_HEADER) $(MISC_EXTRA) $(MISC_SH)
+EXTRA_DIST += misc-utils/MAKEDEV $(MISC_SH)
-dist_man8_MANS += $(MISC_MAN)
-sbin_PROGRAMS += $(MISC_BINS)
sbin_SCRIPTS += $(MISC_SH)
diff --git a/misc-utils/fectest.c b/misc-utils/fectest.c
index fcba513..f560f2b 100644
--- a/misc-utils/fectest.c
+++ b/misc-utils/fectest.c
@@ -21,7 +21,7 @@ int main(void)
unsigned char buf[NR_PKTS * PKT_SIZE];
unsigned char pktbuf[(NR_PKTS + DROPS) * PKT_SIZE];
struct fec_parms *fec;
- unsigned char *srcs[NR_PKTS];
+ unsigned char *srcs[NR_PKTS + DROPS];
unsigned char *pkt[NR_PKTS + DROPS];
int pktnr[NR_PKTS + DROPS];
struct timeval then, now;
@@ -87,6 +87,6 @@ int main(void)
exit(1);
}
- printf("Decoded in %ld.%06lds\n", now.tv_sec, now.tv_usec);
+ printf("Decoded in %ld.%06lds\n", (long)now.tv_sec, (long)now.tv_usec);
return 0;
}
diff --git a/misc-utils/flash_erase.c b/misc-utils/flash_erase.c
index a7fc6a6..c6f6f66 100644
--- a/misc-utils/flash_erase.c
+++ b/misc-utils/flash_erase.c
@@ -2,6 +2,7 @@
Copyright (C) 2000 Arcom Control System Ltd
Copyright (C) 2010 Mike Frysinger <vapier@gentoo.org>
+ Copyright 2021 NXP
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
@@ -50,11 +51,10 @@ static int unlock; /* unlock sectors before erasing */
static struct jffs2_unknown_node cleanmarker;
int target_endian = __BYTE_ORDER;
-static void show_progress(struct mtd_dev_info *mtd, off_t start, int eb,
- int eb_start, int eb_cnt)
+static void show_progress(off_t start, int eb, int eb_start, int eb_cnt, int step)
{
bareverbose(!quiet, "\rErasing %d Kibyte @ %llx -- %2i %% complete ",
- mtd->eb_size / 1024, (unsigned long long)start, ((eb - eb_start) * 100) / eb_cnt);
+ step / 1024, (unsigned long long)start, ((eb - eb_start) * 100) / eb_cnt);
fflush(stdout);
}
@@ -64,13 +64,16 @@ static void display_help (void)
"Erase blocks of the specified MTD device.\n"
"Specify a count of 0 to erase to end of device.\n"
"\n"
- " -j, --jffs2 format the device for jffs2\n"
- " -N, --noskipbad don't skip bad blocks\n"
- " -u, --unlock unlock sectors before erasing\n"
- " -q, --quiet do not display progress messages\n"
- " --silent same as --quiet\n"
- " --help display this help and exit\n"
- " --version output version information and exit\n",
+ " -j, --jffs2 format the device for jffs2\n"
+ " -c, --cleanmarker=SIZE size of jffs2 cleanmarker (default 12)\n"
+ " -N, --noskipbad don't skip bad blocks\n"
+ " -u, --unlock unlock sectors before erasing\n"
+ " -q, --quiet do not display progress messages\n"
+ " --silent same as --quiet\n"
+ " --help display this help and exit\n"
+ " --version output version information and exit\n",
+ "\n"
+ " MTD_DEVICE MTD device node or 'mtd:<name>'\n"
PROGRAM_NAME);
}
@@ -88,14 +91,35 @@ static void display_version (void)
PROGRAM_NAME);
}
+static void clear_marker(libmtd_t mtd_desc, struct mtd_dev_info *mtd, int fd,
+ unsigned int eb, int cmlen, bool isNAND)
+{
+ off_t offset = (off_t)eb * mtd->eb_size;
+
+ /* write cleanmarker */
+ if (isNAND) {
+ if (mtd_write(mtd_desc, mtd, fd, eb, 0, NULL, 0, &cleanmarker, cmlen,
+ MTD_OPS_AUTO_OOB) != 0) {
+ sys_errmsg("%s: MTD writeoob failure", mtd_device);
+ return;
+ }
+ } else {
+ if (pwrite(fd, &cleanmarker, sizeof(cleanmarker), (loff_t)offset) != sizeof(cleanmarker)) {
+ sys_errmsg("%s: MTD write failure", mtd_device);
+ return;
+ }
+ }
+ verbose(!quiet, "%llx : Cleanmarker Updated.", (unsigned long long)offset);
+}
+
int main(int argc, char *argv[])
{
libmtd_t mtd_desc;
struct mtd_dev_info mtd;
- int fd, cmlen = 8;
+ int fd, cmlen = 8, cmsize = sizeof(cleanmarker);
unsigned long long start;
unsigned int eb, eb_start, eb_cnt;
- bool isNAND;
+ bool isNAND, erase_chip = false;
int error = 0;
off_t offset = 0;
@@ -104,11 +128,12 @@ int main(int argc, char *argv[])
*/
for (;;) {
int option_index = 0;
- static const char *short_options = "jNquVh";
+ static const char *short_options = "jc:NquVh";
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"jffs2", no_argument, 0, 'j'},
+ {"cleanmarker", required_argument, 0, 'c'},
{"noskipbad", no_argument, 0, 'N'},
{"quiet", no_argument, 0, 'q'},
{"silent", no_argument, 0, 'q'},
@@ -132,6 +157,9 @@ int main(int argc, char *argv[])
case 'j':
jffs2 = 1;
break;
+ case 'c':
+ cmsize = atoi(optarg);
+ break;
case 'N':
noskipbad = 1;
break;
@@ -148,7 +176,9 @@ int main(int argc, char *argv[])
}
switch (argc - optind) {
case 3:
- mtd_device = argv[optind];
+ mtd_device = mtd_find_dev_node(argv[optind]);
+ if (!mtd_device)
+ return errmsg("Can't find MTD device %s", argv[optind]);
start = simple_strtoull(argv[optind + 1], &error);
eb_cnt = simple_strtoul(argv[optind + 2], &error);
break;
@@ -182,6 +212,10 @@ int main(int argc, char *argv[])
if (jffs2 && mtd.type == MTD_MLCNANDFLASH)
return errmsg("JFFS2 cannot support MLC NAND.");
+ if (jffs2 && cmsize < sizeof(cleanmarker))
+ return errmsg("cleanmarker size must be >= 12");
+ if (jffs2 && cmsize >= mtd.eb_size)
+ return errmsg("cleanmarker size must be < eraseblock size");
eb_start = start / mtd.eb_size;
@@ -191,7 +225,7 @@ int main(int argc, char *argv[])
cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
if (!isNAND) {
- cleanmarker.totlen = cpu_to_je32(sizeof(cleanmarker));
+ cleanmarker.totlen = cpu_to_je32(cmsize);
} else {
cleanmarker.totlen = cpu_to_je32(8);
cmlen = min(mtd.oobavail, 8);
@@ -205,6 +239,47 @@ int main(int argc, char *argv[])
if (eb_cnt == 0)
eb_cnt = (mtd.size / mtd.eb_size) - eb_start;
+ if (eb_start == 0 && mtd.size == eb_cnt * mtd.eb_size)
+ erase_chip = true;
+
+ /* If MTD device may have bad eraseblocks,
+ * erase one by one each sector
+ */
+ if (noskipbad && mtd.bb_allowed)
+ erase_chip = false;
+
+ if (erase_chip) {
+ show_progress(0, eb_start, eb_start, eb_cnt, mtd.size);
+
+ if (unlock) {
+ if (mtd_unlock_multi(&mtd, fd, eb_start, eb_cnt) != 0) {
+ sys_errmsg("%s: MTD unlock entire chip failure." \
+ "Trying one by one each sector.",
+ mtd_device);
+ goto erase_each_sector;
+ }
+ }
+
+ if (mtd_erase_multi(mtd_desc, &mtd, fd, eb_start, eb_cnt) != 0) {
+ sys_errmsg("%s: MTD Erase entire chip failure" \
+ "Trying one by one each sector.",
+ mtd_device);
+ goto erase_each_sector;
+ }
+
+ show_progress(0, eb_start + eb_cnt, eb_start,
+ eb_cnt, mtd.size);
+
+ if (!jffs2)
+ goto out;
+
+ /* write cleanmarker */
+ for (eb = eb_start; eb < eb_start + eb_cnt; eb++)
+ clear_marker(mtd_desc, &mtd, fd, eb, cmlen, isNAND);
+ goto out;
+ }
+
+erase_each_sector:
for (eb = eb_start; eb < eb_start + eb_cnt; eb++) {
offset = (off_t)eb * mtd.eb_size;
@@ -223,7 +298,7 @@ int main(int argc, char *argv[])
}
}
- show_progress(&mtd, offset, eb, eb_start, eb_cnt);
+ show_progress(offset, eb, eb_start, eb_cnt, mtd.eb_size);
if (unlock) {
if (mtd_unlock(&mtd, fd, eb) != 0) {
@@ -237,26 +312,11 @@ int main(int argc, char *argv[])
continue;
}
- /* format for JFFS2 ? */
- if (!jffs2)
- continue;
-
- /* write cleanmarker */
- if (isNAND) {
- if (mtd_write(mtd_desc, &mtd, fd, eb, 0, NULL, 0, &cleanmarker, cmlen,
- MTD_OPS_AUTO_OOB) != 0) {
- sys_errmsg("%s: MTD writeoob failure", mtd_device);
- continue;
- }
- } else {
- if (pwrite(fd, &cleanmarker, sizeof(cleanmarker), (loff_t)offset) != sizeof(cleanmarker)) {
- sys_errmsg("%s: MTD write failure", mtd_device);
- continue;
- }
- }
- verbose(!quiet, " Cleanmarker Updated.");
+ if (jffs2)
+ clear_marker(mtd_desc, &mtd, fd, eb, cmlen, isNAND);
}
- show_progress(&mtd, offset, eb, eb_start, eb_cnt);
+ show_progress(offset, eb, eb_start, eb_cnt, mtd.eb_size);
+out:
bareverbose(!quiet, "\n");
return 0;
diff --git a/misc-utils/flash_otp_dump.c b/misc-utils/flash_otp_dump.c
index f1e1782..324d856 100644
--- a/misc-utils/flash_otp_dump.c
+++ b/misc-utils/flash_otp_dump.c
@@ -20,7 +20,7 @@ int main(int argc,char *argv[])
int offset = 0;
unsigned char buf[16];
- if (argc <= 3 || (strcmp(argv[1], "-f") && strcmp(argv[1], "-u"))) {
+ if (argc < 3 || (strcmp(argv[1], "-f") && strcmp(argv[1], "-u"))) {
fprintf(stderr,"Usage: %s [ -f | -u ] <device> [<offset>]\n", PROGRAM_NAME);
return EINVAL;
}
diff --git a/misc-utils/flash_otp_erase.c b/misc-utils/flash_otp_erase.c
new file mode 100644
index 0000000..771e230
--- /dev/null
+++ b/misc-utils/flash_otp_erase.c
@@ -0,0 +1,64 @@
+/*
+ * flash_otp_erase.c -- erase area of One-Time-Program data
+ */
+
+#define PROGRAM_NAME "flash_otp_erase"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include <mtd/mtd-user.h>
+#include "common.h"
+
+int main(int argc,char *argv[])
+{
+ int fd, val, ret, offset, size;
+ struct otp_info info;
+ char *p;
+
+ if (argc != 5 || strcmp(argv[1], "-u")) {
+ fprintf(stderr, "Usage: %s -u <device> <offset> <size>\n", PROGRAM_NAME);
+ fprintf(stderr, "offset and size must match on OTP region boundaries\n");
+ return EINVAL;
+ }
+
+ fd = open(argv[2], O_WRONLY);
+ if (fd < 0) {
+ perror(argv[2]);
+ return errno;
+ }
+
+ val = MTD_OTP_USER;
+ ret = ioctl(fd, OTPSELECT, &val);
+ if (ret < 0) {
+ perror("OTPSELECT");
+ return errno;
+ }
+
+ offset = strtoul(argv[3], &p, 0);
+ if (argv[3][0] == 0 || *p != 0) {
+ fprintf(stderr, "%s: bad offset value\n", PROGRAM_NAME);
+ return ERANGE;
+ }
+
+ size = strtoul(argv[4], &p, 0);
+ if (argv[4][0] == 0 || *p != 0) {
+ fprintf(stderr, "%s: bad size value\n", PROGRAM_NAME);
+ return ERANGE;
+ }
+
+ info.start = offset;
+ info.length = size;
+ ret = ioctl(fd, OTPERASE, &info);
+ if (ret < 0) {
+ perror("OTPERASE");
+ return errno;
+ }
+
+ return 0;
+}
diff --git a/misc-utils/flash_unlock.c b/misc-utils/flash_unlock.c
index fbbfa51..fa5decb 100644
--- a/misc-utils/flash_unlock.c
+++ b/misc-utils/flash_unlock.c
@@ -51,6 +51,8 @@ static NORETURN void usage(int status)
" -l --lock Lock a region of flash\n"
" -u --unlock Unlock a region of flash\n"
"\n"
+ " <mtd device> MTD device node or 'mtd:<name>'\n"
+ "\n"
"If offset is not specified, it defaults to 0.\n"
"If block count is not specified, it defaults to all blocks.\n"
"A block count of -1 means all blocks.\n",
@@ -125,7 +127,12 @@ static void process_args(int argc, char *argv[])
}
/* First non-option argument */
- dev = argv[arg_idx++];
+ dev = mtd_find_dev_node(argv[arg_idx]);
+ if (!dev) {
+ errmsg("MTD device not found %s", argv[arg_idx]);
+ usage(EXIT_FAILURE);
+ }
+ arg_idx++;
/* Second non-option argument */
if (arg_idx < argc)
diff --git a/misc-utils/flashcp.c b/misc-utils/flashcp.c
index d7b0a59..9c48637 100644
--- a/misc-utils/flashcp.c
+++ b/misc-utils/flashcp.c
@@ -48,7 +48,7 @@
/* for debugging purposes only */
#ifdef DEBUG
#undef DEBUG
-#define DEBUG(fmt,args...) { log_printf (LOG_ERROR,"%d: ",__LINE__); log_printf (LOG_ERROR,fmt,## args); }
+#define DEBUG(fmt,args...) { fprintf (stderr,"%d: ",__LINE__); fprintf (stderr,fmt,## args); }
#else
#undef DEBUG
#define DEBUG(fmt,args...)
@@ -57,36 +57,47 @@
#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
#define FLAG_ERASE_ALL 0x10
+#define FLAG_PARTITION 0x20
+#define FLAG_WR_LAST 0x40
/* error levels */
#define LOG_NORMAL 1
#define LOG_ERROR 2
-static void log_printf (int level,const char *fmt, ...)
+static NORETURN void log_failure (const char *fmt, ...)
{
- FILE *fp = level == LOG_NORMAL ? stdout : stderr;
va_list ap;
va_start (ap,fmt);
- vfprintf (fp,fmt,ap);
+ vfprintf (stderr,fmt,ap);
va_end (ap);
- fflush (fp);
+ fflush (stderr);
+
+ exit (EXIT_FAILURE);
}
-static NORETURN void showusage(bool error)
+static int verbose = 0;
+static void log_verbose (const char *fmt, ...)
{
- int level = error ? LOG_ERROR : LOG_NORMAL;
+ va_list ap;
+
+ if (!verbose)
+ return;
+
+ va_start (ap,fmt);
+ vfprintf (stdout,fmt,ap);
+ va_end (ap);
+ fflush (stdout);
+}
- log_printf (level,
+static NORETURN void showusage(bool error)
+{
+ fprintf (error ? stderr : stdout,
"\n"
"Flash Copy - Written by Abraham van der Merwe <abraham@2d3d.co.za>\n"
"\n"
@@ -94,12 +105,14 @@ static NORETURN void showusage(bool error)
" %1$s -h | --help\n"
" %1$s -V | --version\n"
"\n"
- " -h | --help Show this help message\n"
- " -v | --verbose Show progress reports\n"
- " -A | --erase-all Erases the whole device regardless of the image size\n"
- " -V | --version Show version information and exit\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"
+ " -h | --help Show this help message\n"
+ " -v | --verbose Show progress reports\n"
+ " -p | --partition Only copy different block from file to device\n"
+ " -A | --erase-all Erases the whole device regardless of the image size\n"
+ " -l | --wr-last=bytes Write the first [bytes] last\n"
+ " -V | --version Show version information and exit\n"
+ " <filename> File which you want to copy to flash\n"
+ " <device> Flash device node or 'mtd:<name>' to write to (e.g. /dev/mtd0, /dev/mtd1, mtd:data, etc.)\n"
"\n",
PROGRAM_NAME);
@@ -108,49 +121,85 @@ static NORETURN void showusage(bool error)
static int safe_open (const char *pathname,int flags)
{
+ const char *access = "unknown";
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");
+ access = "read/write";
else if (flags & O_RDONLY)
- log_printf (LOG_ERROR," for read access");
+ access = "read";
else if (flags & O_WRONLY)
- log_printf (LOG_ERROR," for write access");
- log_printf (LOG_ERROR,": %m\n");
- exit (EXIT_FAILURE);
+ access = "write";
+
+ log_failure ("While trying to open %s for %s access: %m\n",pathname,access);
}
return (fd);
}
-static void safe_read (int fd,const char *filename,void *buf,size_t count,bool verbose)
+static void safe_read (int fd,const char *filename,void *buf,size_t count)
{
ssize_t result;
result = read (fd,buf,count);
if (count != result)
{
- if (verbose) log_printf (LOG_NORMAL,"\n");
+ log_verbose ("\n");
+ if (result < 0)
+ {
+ log_failure("While reading data from %s: %m\n",filename);
+ }
+ log_failure("Short read count returned while reading from %s\n",filename);
+ }
+}
+
+static void safe_write (int fd,const void *buf,size_t count,size_t written,unsigned long long to_write,const char *device)
+{
+ ssize_t result;
+
+ /* write to device */
+ result = write (fd,buf,count);
+ if (count != result)
+ {
+ log_verbose ("\n");
if (result < 0)
{
- log_printf (LOG_ERROR,"While reading data from %s: %m\n",filename);
- exit (EXIT_FAILURE);
+ log_failure("While writing data to 0x%.8lx-0x%.8lx on %s: %m\n",
+ written,written + count,device);
}
- log_printf (LOG_ERROR,"Short read count returned while reading from %s\n",filename);
- exit (EXIT_FAILURE);
+ log_failure("Short write count returned while writing to x%.8zx-0x%.8zx on %s: %zu/%llu bytes written to flash\n",
+ written,written + count,device,written + result,to_write);
}
}
+static off_t safe_lseek (int fd,off_t offset,int whence,const char *filename)
+{
+ off_t off;
+
+ off = lseek (fd,offset,whence);
+ if (off < 0)
+ {
+ log_failure("While seeking on %s: %m\n",filename);
+ }
+
+ return off;
+}
+
static void safe_rewind (int fd,const char *filename)
{
- if (lseek (fd,0L,SEEK_SET) < 0)
+ safe_lseek(fd,0L,SEEK_SET,filename);
+}
+
+static void safe_memerase (int fd,const char *device,struct erase_info_user *erase)
+{
+ if (ioctl (fd,MEMERASE,erase) < 0)
{
- log_printf (LOG_ERROR,"While seeking to start of %s: %m\n",filename);
- exit (EXIT_FAILURE);
+ log_verbose ("\n");
+ log_failure("While erasing blocks 0x%.8x-0x%.8x on %s: %m\n",
+ (unsigned int) erase->start,(unsigned int) (erase->start + erase->length),device);
}
}
@@ -168,12 +217,13 @@ 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];
+ unsigned char *src,*dest,*wrlast_buf;
+ unsigned long long wrlast_len = 0;
+ int error = 0;
/*********************
* parse cmd-line
@@ -181,11 +231,13 @@ int main (int argc,char *argv[])
for (;;) {
int option_index = 0;
- static const char *short_options = "hvAV";
+ static const char *short_options = "hvpAl:V";
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"verbose", no_argument, 0, 'v'},
+ {"partition", no_argument, 0, 'p'},
{"erase-all", no_argument, 0, 'A'},
+ {"wr-last", required_argument, 0, 'l'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
};
@@ -202,13 +254,21 @@ int main (int argc,char *argv[])
DEBUG("Got FLAG_HELP\n");
break;
case 'v':
- flags |= FLAG_VERBOSE;
+ verbose = 1;
DEBUG("Got FLAG_VERBOSE\n");
break;
+ case 'p':
+ flags |= FLAG_PARTITION;
+ DEBUG("Got FLAG_PARTITION");
+ break;
case 'A':
flags |= FLAG_ERASE_ALL;
DEBUG("Got FLAG_ERASE_ALL\n");
break;
+ case 'l':
+ flags |= FLAG_WR_LAST;
+ wrlast_len = simple_strtoll(optarg, &error);
+ break;
case 'V':
common_print_version();
exit(EXIT_SUCCESS);
@@ -224,13 +284,23 @@ int main (int argc,char *argv[])
DEBUG("Got filename: %s\n",filename);
flags |= FLAG_DEVICE;
- device = argv[optind+1];
+ device = mtd_find_dev_node(argv[optind+1]);
+ if (!device)
+ log_failure("Failed to find device %s\n", argv[optind+1]);
+
DEBUG("Got device: %s\n",device);
}
if (flags & FLAG_HELP || device == NULL)
showusage(flags != FLAG_HELP);
+ if (flags & FLAG_PARTITION && flags & FLAG_ERASE_ALL)
+ log_failure("Option --partition does not support --erase-all\n");
+
+ if (flags & FLAG_PARTITION && flags & FLAG_WR_LAST) {
+ log_failure("Option --partition does not support --wr-last\n");
+ }
+
atexit (cleanup);
/* get some info about the flash device */
@@ -238,23 +308,30 @@ int main (int argc,char *argv[])
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);
+ log_failure("This doesn't seem to be a valid MTD flash device!\n");
}
/* 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);
- }
+ log_failure("While trying to get the file status of %s: %m\n",filename);
/* does it fit into the device/partition? */
if (filestat.st_size > mtd.size)
+ log_failure("%s won't fit into %s!\n",filename,device);
+
+ src = malloc(mtd.erasesize);
+ if (!src)
+ log_failure("Malloc failed");
+
+ dest = malloc(mtd.erasesize);
+ if (!dest)
+ log_failure("Malloc failed");
+
+ /* diff block flashcp */
+ if (flags & FLAG_PARTITION)
{
- log_printf (LOG_ERROR,"%s won't fit into %s!\n",filename,device);
- exit (EXIT_FAILURE);
+ goto DIFF_BLOCKS;
}
/*****************************************************
@@ -275,37 +352,24 @@ int main (int argc,char *argv[])
erase.length *= mtd.erasesize;
}
- if (flags & FLAG_VERBOSE)
+ if (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);
+ log_verbose ("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);
- }
+ log_verbose ("\rErasing blocks: %d/%d (%d%%)",i,blocks,PERCENTAGE (i,blocks));
+ safe_memerase(dev_fd,device,&erase);
erase.start += mtd.erasesize;
}
- log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d (100%%)\n",blocks,blocks);
+ log_verbose ("\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);
- }
+ safe_memerase(dev_fd,device,&erase);
}
DEBUG("Erased %u / %luk bytes\n",erase.length,filestat.st_size);
@@ -313,50 +377,68 @@ int main (int argc,char *argv[])
* write the entire file to flash *
**********************************/
- if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"Writing data: 0k/%lluk (0%%)",KB ((unsigned long long)filestat.st_size));
size = filestat.st_size;
- i = BUFSIZE;
+ i = mtd.erasesize;
written = 0;
+
+ if ((flags & FLAG_WR_LAST) && (filestat.st_size > wrlast_len)) {
+ if (wrlast_len > mtd.erasesize)
+ log_failure("The wrlast (%lluk) is larger than erasesize (%lluk)\n", KB (wrlast_len), KB ((unsigned long long)mtd.erasesize));
+
+ if (size < mtd.erasesize) i = size;
+
+ log_verbose ("Reading %lluk of data to write last.\n", KB ((unsigned long long)wrlast_len));
+ wrlast_buf = malloc(wrlast_len);
+ if (!wrlast_buf)
+ log_failure("Malloc failed");
+ safe_read (fil_fd, filename, wrlast_buf, wrlast_len);
+ safe_lseek(dev_fd, wrlast_len, SEEK_SET, device);
+ written += wrlast_len;
+ size -= wrlast_len;
+ i -= wrlast_len;
+
+ log_verbose ("Writing remaining erase block data: %dk/%lluk (%llu%%)\n",
+ KB (written + i),
+ KB ((unsigned long long)filestat.st_size),
+ PERCENTAGE ((unsigned long long)written + i, (unsigned long long)filestat.st_size));
+ safe_read (fil_fd, filename, src, i);
+ safe_write(dev_fd, src, i, written, (unsigned long long)filestat.st_size, device);
+
+ written += i;
+ size -= i;
+ i = mtd.erasesize;
+ } else {
+ log_verbose ("Writing data: 0k/%lluk (0%%)",KB ((unsigned long long)filestat.st_size));
+ }
+
while (size)
{
- if (size < BUFSIZE) i = size;
- if (flags & FLAG_VERBOSE)
- log_printf (LOG_NORMAL,"\rWriting data: %dk/%lluk (%llu%%)",
- KB (written + i),
- KB ((unsigned long long)filestat.st_size),
- PERCENTAGE (written + i,(unsigned long long)filestat.st_size));
+ if (size < mtd.erasesize) i = size;
+ log_verbose ("\rWriting data: %dk/%lluk (%llu%%)",
+ KB (written + i),
+ KB ((unsigned long long)filestat.st_size),
+ PERCENTAGE ((unsigned long long)written + i,(unsigned long long)filestat.st_size));
/* read from filename */
- safe_read (fil_fd,filename,src,i,flags & FLAG_VERBOSE);
+ safe_read (fil_fd,filename,src,i);
/* 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%.8lx-0x%.8lx on %s: %m\n",
- written,written + i,device);
- exit (EXIT_FAILURE);
- }
- log_printf (LOG_ERROR,
- "Short write count returned while writing to x%.8zx-0x%.8zx on %s: %zu/%llu bytes written to flash\n",
- written,written + i,device,written + result,(unsigned long long)filestat.st_size);
- exit (EXIT_FAILURE);
- }
+ safe_write(dev_fd,src,i,written,(unsigned long long)filestat.st_size,device);
written += i;
size -= i;
}
- if (flags & FLAG_VERBOSE)
- log_printf (LOG_NORMAL,
- "\rWriting data: %lluk/%lluk (100%%)\n",
- KB ((unsigned long long)filestat.st_size),
- KB ((unsigned long long)filestat.st_size));
+ log_verbose ("\rWriting data: %lluk/%lluk (100%%)\n",
+ KB ((unsigned long long)filestat.st_size),
+ KB ((unsigned long long)filestat.st_size));
DEBUG("Wrote %d / %lluk bytes\n",written,(unsigned long long)filestat.st_size);
+ if ((flags & FLAG_WR_LAST) && (filestat.st_size > wrlast_len)) {
+ log_verbose ("Writing %lluk of the write last data.\n", KB ((unsigned long long)wrlast_len));
+ safe_rewind (dev_fd, device);
+ safe_write(dev_fd, wrlast_buf, wrlast_len, 0, wrlast_len, device);
+ }
+
/**********************************
* verify that flash == file data *
**********************************/
@@ -364,43 +446,96 @@ int main (int argc,char *argv[])
safe_rewind (fil_fd,filename);
safe_rewind (dev_fd,device);
size = filestat.st_size;
- i = BUFSIZE;
+ i = mtd.erasesize;
written = 0;
- if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"Verifying data: 0k/%lluk (0%%)",KB ((unsigned long long)filestat.st_size));
+ log_verbose ("Verifying data: 0k/%lluk (0%%)",KB ((unsigned long long)filestat.st_size));
while (size)
{
- if (size < BUFSIZE) i = size;
- if (flags & FLAG_VERBOSE)
- log_printf (LOG_NORMAL,
- "\rVerifying data: %luk/%lluk (%llu%%)",
- KB (written + i),
- KB ((unsigned long long)filestat.st_size),
- PERCENTAGE (written + i,(unsigned long long)filestat.st_size));
+ if (size < mtd.erasesize) i = size;
+ log_verbose ("\rVerifying data: %luk/%lluk (%llu%%)",
+ KB (written + i),
+ KB ((unsigned long long)filestat.st_size),
+ PERCENTAGE ((unsigned long long)written + i,(unsigned long long)filestat.st_size));
/* read from filename */
- safe_read (fil_fd,filename,src,i,flags & FLAG_VERBOSE);
+ safe_read (fil_fd,filename,src,i);
/* read from device */
- safe_read (dev_fd,device,dest,i,flags & FLAG_VERBOSE);
+ safe_read (dev_fd,device,dest,i);
/* compare buffers */
if (memcmp (src,dest,i))
- {
- log_printf (LOG_ERROR,
- "File does not seem to match flash data. First mismatch at 0x%.8zx-0x%.8zx\n",
+ log_failure("File does not seem to match flash data. First mismatch at 0x%.8zx-0x%.8zx\n",
written,written + i);
- exit (EXIT_FAILURE);
- }
written += i;
size -= i;
}
- if (flags & FLAG_VERBOSE)
- log_printf (LOG_NORMAL,
- "\rVerifying data: %lluk/%lluk (100%%)\n",
- KB ((unsigned long long)filestat.st_size),
- KB ((unsigned long long)filestat.st_size));
+ log_verbose ("\rVerifying data: %lluk/%lluk (100%%)\n",
+ KB ((unsigned long long)filestat.st_size),
+ KB ((unsigned long long)filestat.st_size));
DEBUG("Verified %d / %lluk bytes\n",written,(unsigned long long)filestat.st_size);
exit (EXIT_SUCCESS);
+
+ /*********************************************
+ * Copy different blocks from file to device *
+ ********************************************/
+DIFF_BLOCKS:
+ safe_rewind (fil_fd,filename);
+ safe_rewind (dev_fd,device);
+ size = filestat.st_size;
+ i = mtd.erasesize;
+ erase.start = 0;
+ erase.length = (filestat.st_size + mtd.erasesize - 1) / mtd.erasesize;
+ erase.length *= mtd.erasesize;
+ written = 0;
+ unsigned long current_dev_block = 0;
+ int diffBlock = 0;
+ int blocks = erase.length / mtd.erasesize;
+ erase.length = mtd.erasesize;
+
+ log_verbose ("\rProcessing blocks: 0/%d (%d%%)", blocks, PERCENTAGE (0,blocks));
+ for (int s = 1; s <= blocks; s++)
+ {
+ if (size < mtd.erasesize) i = size;
+ log_verbose ("\rProcessing blocks: %d/%d (%d%%)", s, blocks, PERCENTAGE (s,blocks));
+
+ /* read from filename */
+ safe_read (fil_fd,filename,src,i);
+
+ /* read from device */
+ current_dev_block = safe_lseek(dev_fd, 0, SEEK_CUR, device);
+ safe_read (dev_fd,device,dest,i);
+
+ /* compare buffers, if not the same, erase and write the block */
+ if (memcmp (src,dest,i))
+ {
+ diffBlock++;
+ /* erase block */
+ safe_lseek(dev_fd, current_dev_block, SEEK_SET, device);
+ safe_memerase(dev_fd,device,&erase);
+
+ /* write to device */
+ safe_lseek(dev_fd, current_dev_block, SEEK_SET, device);
+ safe_write(dev_fd,src,i,written,(unsigned long long)filestat.st_size,device);
+
+ /* read from device */
+ safe_lseek(dev_fd, current_dev_block, SEEK_SET, device);
+ safe_read (dev_fd,device,dest,i);
+
+ /* compare buffers for write success */
+ if (memcmp (src,dest,i))
+ log_failure("File does not seem to match flash data. First mismatch at 0x%.8zx-0x%.8zx\n",
+ written,written + i);
+ }
+
+ erase.start += i;
+ written += i;
+ size -= i;
+ }
+
+ log_verbose ("\ndiff blocks: %d\n", diffBlock);
+
+ exit (EXIT_SUCCESS);
}
diff --git a/misc-utils/lsmtd.8 b/misc-utils/lsmtd.8
index 3061c40..198c8a7 100644
--- a/misc-utils/lsmtd.8
+++ b/misc-utils/lsmtd.8
@@ -14,7 +14,7 @@ command reads the
.B sysfs
filesystem to gather information. Alternatively, the
.B procfs
-filesystem and ioctl interfaces are used, should the sysfs filesytem not
+filesystem and ioctl interfaces are used, should the sysfs filesystem not
be available.
.PP
The command prints all MTD and UBI devices in a pretty-printed list format by
diff --git a/misc-utils/lsmtd.c b/misc-utils/lsmtd.c
index 24a30ac..b62b69f 100644
--- a/misc-utils/lsmtd.c
+++ b/misc-utils/lsmtd.c
@@ -72,11 +72,11 @@ static struct column cols[] = {
{ "SUB-SIZE", "subpage size", COL_SUBSIZE, COL_DT_SIZE, 0 },
{ "OOB-SIZE", "out of band data size", COL_OOBSIZE, COL_DT_SIZE, 0 },
{ "RO", "read-only device", COL_RO, COL_DT_BOOL, 0 },
- { "CORRUPTED", "wheather an UBI volume is corrupted",
+ { "CORRUPTED", "whether an UBI volume is corrupted",
COL_CORRUPTED, COL_DT_BOOL, 0 },
{ "REGIONS", "number of additional erase regions",
COL_REGION, COL_DT_NUMBER, 0 },
- { "BB", "wheather the MTD device may have bad eraseblocks",
+ { "BB", "whether the MTD device may have bad eraseblocks",
COL_BB, COL_DT_BOOL, 0 },
{ "MAX-EC", "current highest erase counter value on UBI devices",
COL_MAXEC, COL_DT_NUMBER, 0 },
@@ -107,7 +107,7 @@ static NORETURN void usage(int status)
" -r, --raw Use raw output format\n"
" -P, --pairs Use key=\"value\" output format\n"
" -J, --json Use JSON output format\n"
-" -o, --output <list> Comma seperated list of columns to print\n"
+" -o, --output <list> Comma separated list of columns to print\n"
" -O, --output-all Print all columns\n"
" -x, --sort <column> Sort output by <column>\n"
" -m, --no-ubi Do not display information about UBI devices/volumes\n"
diff --git a/misc-utils/lsmtd_scan.c b/misc-utils/lsmtd_scan.c
index cec7b5c..9331c5b 100644
--- a/misc-utils/lsmtd_scan.c
+++ b/misc-utils/lsmtd_scan.c
@@ -162,7 +162,7 @@ int scan_ubi(libubi_t lib_ubi)
}
if (j == num_mtd_devices) {
- fprintf(stderr, "Cannot find mtd device %d refered to "
+ fprintf(stderr, "Cannot find mtd device %d referred to "
"by ubi device %d\n", dev_info.mtd_num,
dev_info.dev_num);
return -1;
diff --git a/misc-utils/mtd_debug.c b/misc-utils/mtd_debug.c
index c0b7109..abee5e3 100644
--- a/misc-utils/mtd_debug.c
+++ b/misc-utils/mtd_debug.c
@@ -348,6 +348,7 @@ int main(int argc, char *argv[])
{
int err = 0, fd;
int open_flag;
+ char *dev;
enum {
OPT_INFO,
@@ -369,8 +370,12 @@ int main(int argc, char *argv[])
showusage();
/* open device */
+ dev = mtd_find_dev_node(argv[2]);
+ if (!dev)
+ errmsg_die("Failed to find MTD device %s", argv[2]);
+
open_flag = (option == OPT_INFO || option == OPT_READ) ? O_RDONLY : O_RDWR;
- if ((fd = open(argv[2], O_SYNC | open_flag)) < 0)
+ if ((fd = open(dev, O_SYNC | open_flag)) < 0)
errmsg_die("open()");
switch (option) {
diff --git a/misc-utils/mtdpart.c b/misc-utils/mtdpart.c
index ba35d87..a341148 100644
--- a/misc-utils/mtdpart.c
+++ b/misc-utils/mtdpart.c
@@ -36,8 +36,10 @@ static void display_help(int status)
" -h, --help Display this help and exit\n"
" -V, --version Output version information and exit\n"
"\n"
+" <MTD_DEVICE> MTD device node or 'mtd:<name>'\n"
+"\n"
"START location and SIZE of the partition are in bytes. They should align on\n"
-"eraseblock size.\n",
+"eraseblock size. If SIZE is 0 the partition will go to end of MTD device.\n",
PROGRAM_NAME
);
exit(status);
@@ -106,7 +108,10 @@ static void process_options(int argc, char * const argv[])
display_help(EXIT_FAILURE);
const char *s_command = argv[optind++];
- mtddev = argv[optind++];
+ mtddev = mtd_find_dev_node(argv[optind]);
+ if (!mtddev)
+ errmsg_die("MTD device not found %s", argv[optind]);
+ optind++;
if (strcmp(s_command, "del") == 0 && (argc - optind) == 1) {
const char *s_part_no = argv[optind++];