diff options
author | Bjørn Mork <bjorn@mork.no> | 2015-04-16 01:51:59 +0200 |
---|---|---|
committer | Bjørn Mork <bjorn@mork.no> | 2015-04-16 01:51:59 +0200 |
commit | d5bca655c0f4e88fe847b6f9fa318b06f0240358 (patch) | |
tree | 4e6e5aa42773a573ec177ee531517500f4fe1e30 | |
parent | 4a9f40eceb4fd38ca4a37b74cce92a957e270976 (diff) |
covery: erase partition when full
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r-- | covery/src/covery.c | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/covery/src/covery.c b/covery/src/covery.c index a03a07c..e032300 100644 --- a/covery/src/covery.c +++ b/covery/src/covery.c @@ -40,7 +40,8 @@ static const struct option long_options[] = { const char *program; -static void usage(int ex) { +static void usage(int ex) +{ fprintf(stderr, "Usage: %s [options]\n" " Updates recovery information\n" @@ -99,7 +100,8 @@ static int mtd_open(const char *mtd, struct mtd_info_user *info) return fd; } -const char *stype(__u8 type) { +const char *stype(__u8 type) +{ switch (type) { case MTD_ABSENT: return "absent"; @@ -122,7 +124,8 @@ const char *stype(__u8 type) { } } -static char *sflags(__u32 flags) { +static char *sflags(__u32 flags) +{ static char s[64]; s[0] = 0; @@ -137,7 +140,8 @@ static char *sflags(__u32 flags) { return s; } -void dump_info(struct mtd_info_user *info) { +void dump_info(struct mtd_info_user *info) +{ fprintf(stderr, "type:\t%s (%hhu)\n", stype(info->type), info->type); fprintf(stderr, "flags:\t%s (%#010x)\n", sflags(info->flags), info->flags); fprintf(stderr, "size:\t%#010x\n", info->size); @@ -147,11 +151,13 @@ void dump_info(struct mtd_info_user *info) { fprintf(stderr, "records:\t%u\n", info->size / RECSZ); } -int rec_ok(struct s_env_rec *rec) { +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)); } -void rec_zero(struct s_env_rec *rec) { +void rec_zero(struct s_env_rec *rec) +{ rec->magic = cpu_to_le32(MAGIC); rec->count = 0; rec->check = rec->magic; @@ -173,11 +179,24 @@ int find_mtd(const char *name) return i; } +int erase_mtd(int fd, struct mtd_info_user *info) +{ + struct erase_info_user erase; + + erase.start = 0; + erase.length = info->size; + ioctl(fd, MEMUNLOCK, &erase); + if (ioctl (fd, MEMERASE, &erase) < 0) + return -1; + return 0; +} + int main(int argc, char *argv[]) { int opt, i, fd, cmd = 0, verbose = 0; struct s_env_rec rec; char *p; + off_t pos; program = argv[0]; if (argc < 2 ) @@ -211,7 +230,7 @@ int main(int argc, char *argv[]) } } /* dump requires type */ - if (cmd == 'd') + if (cmd == 'd' || !cmd) usage(EX_USAGE); i = find_mtd(s_env); @@ -237,7 +256,7 @@ int main(int argc, char *argv[]) #endif if (verbose) fprintf(stderr, "\nrec magic count check\n"); - for (i = 1;; i++) { + for (i = 0;; i++) { if (read(fd, buf, RECSZ) != RECSZ) break; if (rec_ok((struct s_env_rec *)buf)) { @@ -250,17 +269,28 @@ int main(int argc, char *argv[]) } else break; } - if (i < 2) { + if (i < 1) { /* bugger out if we never read anything sane */ - fprintf(stderr, "ERROR: failed to read any valid records from %s\n", buf); + fprintf(stderr, "ERROR: failed to read any valid records from %s\n", s_env); 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)); + if (i >= info.size / RECSZ) { + /* erase and restart if partition is full */ + if (verbose) + fprintf(stderr, "%s is full. Erasing all records\n", s_env); + if (erase_mtd(fd, &info) < 0) + fprintf(stderr, "ERROR: failed to erase %s\n", s_env); + i = 0; + pos = lseek(fd, 0, SEEK_SET); + } else { + /* rewind one record after last failed read */ + pos = lseek(fd, -RECSZ, SEEK_CUR); + } + fprintf(stderr, "updating boot_count page[%d]:%05x\n", i, pos); memset(buf, 0xff, RECSZ); rec_zero((struct s_env_rec *)buf); if (write(fd, buf, RECSZ) != RECSZ) |