summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2015-04-16 00:33:16 +0200
committerBjørn Mork <bjorn@mork.no>2015-04-16 00:33:16 +0200
commit67d1ed10ff85433b68f80dbd83874d90a0ce4cb4 (patch)
treeb6bdf3362c1c1b430908e6a8a8f62cf502a34735
parent7a6989e8d87a95921af9c9bcc5b7599c3d353fe2 (diff)
covery: imitate options
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--covery/src/covery.c174
1 files changed, 137 insertions, 37 deletions
diff --git a/covery/src/covery.c b/covery/src/covery.c
index af0bde6..a03a07c 100644
--- a/covery/src/covery.c
+++ b/covery/src/covery.c
@@ -12,10 +12,51 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <getopt.h>
+#include <sysexits.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <mtd/mtd-user.h>
+#define VERSION "0.00"
+
+#ifdef TEST
+static const char s_env[] = "\"mtdram test device\"";
+#else
+static const char s_env[] = "\"s_env\"";
+#endif
+
+static const struct option long_options[] = {
+ { "show", 0, NULL, 'i' },
+ { "clear", 0, NULL, 'c' },
+ { "dump", 0, NULL, 'd' },
+ { "hex", 0, NULL, 'x' },
+ { "ascii", 0, NULL, 'a' },
+ { "verbose", 0, NULL, 'v' },
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { 0, 0, 0, 0 }
+};
+
+const char *program;
+
+static void usage(int ex) {
+ fprintf(stderr,
+ "Usage: %s [options]\n"
+ " Updates recovery information\n"
+ "Options:\n"
+ " -i --show Show current boot count info\n"
+ " -c --clear Clear boot count info\n"
+ " -dx --dump --hex Dump hex of %s data\n"
+ " -da --dump --ascii Ascii of %s data\n"
+ " -v --verbose Verbose output\n"
+ " -h --help Display this text\n"
+ " -V --version Display version\n",
+ program, s_env, s_env);
+ exit(ex);
+}
+
+/* FIXME: verify these magic constants - RECSZ seems to match writesize */
#define MAGIC 0x20110811
#define RECSZ 2048
@@ -33,25 +74,14 @@ struct s_env_rec {
__le32 magic;
__le32 count;
__le32 check;
- __u8 padding[RECSZ - 3 * sizeof(__le32)];
};
-static int nowrite = 1;
-
-#ifdef TEST
-static const char s_env[] = "\"mtdram test device\"";
-#else
-static const char s_env[] = "\"s_env\"";
-#endif
-
-
/* use globals to reduce stack abuse */
struct mtd_info_user info;
struct erase_info_user li;
-struct s_env_rec rec;
-char buf[256];
+char buf[RECSZ];
-int mtd_open(const char *mtd, struct mtd_info_user *info)
+static int mtd_open(const char *mtd, struct mtd_info_user *info)
{
int fd;
@@ -114,18 +144,17 @@ void dump_info(struct mtd_info_user *info) {
fprintf(stderr, "erasesize:\t%#010x\n", info->erasesize);
fprintf(stderr, "writesize:\t%#010x\n", info->writesize);
fprintf(stderr, "oobsize:\t%#010x\n", info->oobsize);
+ fprintf(stderr, "records:\t%u\n", info->size / RECSZ);
}
int rec_ok(struct s_env_rec *rec) {
return (rec->magic == cpu_to_le32(MAGIC) && cpu_to_le32(rec->magic) + cpu_to_le32(rec->count) == cpu_to_le32(rec->check));
}
-int write_ok(int fd, struct s_env_rec *rec) {
- memset(rec, 0xff, sizeof(*rec));
+void rec_zero(struct s_env_rec *rec) {
rec->magic = cpu_to_le32(MAGIC);
rec->count = 0;
rec->check = rec->magic;
- return write(fd, rec, sizeof(*rec));
}
int find_mtd(const char *name)
@@ -146,7 +175,44 @@ int find_mtd(const char *name)
int main(int argc, char *argv[])
{
- int i, fd, bootcount = 0;
+ int opt, i, fd, cmd = 0, verbose = 0;
+ struct s_env_rec rec;
+ char *p;
+
+ program = argv[0];
+ if (argc < 2 )
+ usage(EX_USAGE);
+ optopt = 0;
+ while ((opt = getopt_long(argc, argv, "+icdxavhV?", long_options, NULL)) != EOF ) {
+ switch(opt) {
+ case 'i':
+ case 'c':
+ case 'd':
+ if (cmd)
+ usage(EX_USAGE);
+ cmd = opt;
+ break;
+ case 'x':
+ case 'a':
+ if (cmd != 'd')
+ usage(EX_USAGE);
+ cmd = opt;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ fprintf(stderr, "%s (%s)\n", program, VERSION);
+ exit(0);
+ default:
+ /* optopt will be set if this was an unrecognized option, i.e. *not* 'h' or '?' */
+ usage(optopt ? EX_USAGE : 0);
+ break;
+ }
+ }
+ /* dump requires type */
+ if (cmd == 'd')
+ usage(EX_USAGE);
i = find_mtd(s_env);
if (i < 0) {
@@ -154,34 +220,68 @@ int main(int argc, char *argv[])
return -1;
}
sprintf(buf, "/dev/mtd%d", i);
- fprintf(stderr, "name:\t%s\n", s_env);
- fprintf(stderr, "chrdev:\t%s\n", buf);
+ if (verbose) {
+ fprintf(stderr, "name:\t%s\n", s_env);
+ fprintf(stderr, "chrdev:\t%s\n", buf);
+ }
fd = mtd_open(buf, &info);
if (fd > 0) {
- dump_info(&info);
- fprintf(stderr, "rec magic count check\n");
+ if (verbose)
+ dump_info(&info);
+#ifndef TEST
+ if (info.writesize != RECSZ) {
+ fprintf(stderr, "ERROR: unexpected writesize != recordsize (%u)\n", RECSZ);
+ close(fd);
+ return -1;
+ }
+#endif
+ if (verbose)
+ fprintf(stderr, "\nrec magic count check\n");
for (i = 1;; i++) {
- if (read(fd, &rec, sizeof(rec)) != sizeof(rec))
+ if (read(fd, buf, RECSZ) != RECSZ)
break;
- if (rec_ok(&rec)) {
- fprintf(stderr, "%3u: %#010x %#010x %#010x\n",
- i, le32_to_cpu(rec.magic), le32_to_cpu(rec.count), le32_to_cpu(rec.check));
- bootcount = le32_to_cpu(rec.count);
+ if (rec_ok((struct s_env_rec *)buf)) {
+ memcpy(&rec, buf, sizeof(rec));
+ if (verbose)
+ /* avoid %#010x format for values being 0 */
+ fprintf(stderr, "%3u: %#010x 0x%08x %#010x\n",
+ i, le32_to_cpu(rec.magic), le32_to_cpu(rec.count),
+ le32_to_cpu(rec.check));
} else
break;
}
- /* bugger out if we never read anything sane */
if (i < 2) {
- fprintf(stderr, "ERROR: failed to read any valid records\n");
- } else {
- fprintf(stderr, "bootcount=%u\n", bootcount);
- if (!nowrite) {
- /* rewind after last failed read */
- lseek(fd, -RECSZ, SEEK_CUR);
- fprintf(stderr, "adding record #%d\n", i);
- if (write_ok(fd, &rec) != sizeof(rec))
- fprintf(stderr, "ERROR: failed to save a null record\n");
- }
+ /* bugger out if we never read anything sane */
+ fprintf(stderr, "ERROR: failed to read any valid records from %s\n", buf);
+ close(fd);
+ return -1;
+ }
+ if (cmd == 'i')
+ fprintf(stderr, "boot_count:%u, next_record:%u\n", le32_to_cpu(rec.count), i);
+ if (cmd == 'c') {
+ /* rewind one record after last failed read */
+ fprintf(stderr, "updating boot_count page[%d]:%x\n", i, lseek(fd, -RECSZ, SEEK_CUR));
+ memset(buf, 0xff, RECSZ);
+ rec_zero((struct s_env_rec *)buf);
+ if (write(fd, buf, RECSZ) != RECSZ)
+ fprintf(stderr, "ERROR: failed to update boot_count\n");
+ }
+ if (cmd == 'x' || cmd == 'a') {
+ p = (char *)&rec;
+ fprintf(stderr, "\nErase Size: %d, Write Size: %d\nRecords read: %d\n",
+ info.erasesize, info.writesize, i - 1);
+ }
+ if (cmd == 'x') {
+ fprintf(stderr, "Hex Dump of record:\n000000: ");
+ for (i = 0; i < sizeof(rec); i++)
+ fprintf(stderr, " %02x", p[i]);
+ fprintf(stderr, "\n");
+ }
+ if (cmd == 'a') {
+ fprintf(stderr, "%s data:\n===============================\n", s_env);
+ for (i = 0; i < sizeof(rec); i++)
+ fprintf(stderr, "%c", p[i]);
+ fprintf(stderr, "\n===============================\n%d bytes\n", sizeof(rec));
}
close(fd);
}