summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2015-04-16 01:51:59 +0200
committerBjørn Mork <bjorn@mork.no>2015-04-16 01:51:59 +0200
commitd5bca655c0f4e88fe847b6f9fa318b06f0240358 (patch)
tree4e6e5aa42773a573ec177ee531517500f4fe1e30
parent4a9f40eceb4fd38ca4a37b74cce92a957e270976 (diff)
covery: erase partition when full
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--covery/src/covery.c54
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)