dnsmasq: full: disable ipset support by default
[openwrt/staging/mkresin.git] / package / system / mtd / src / mtd.c
index 55a3bdba8105dea7c6260b32e2f652c9225a1861..fc7071d940833d2595b1cf57bc14e6671f8d5dc1 100644 (file)
@@ -44,6 +44,7 @@
 #include <sys/reboot.h>
 #include <linux/reboot.h>
 #include <mtd/mtd-user.h>
+#include "crc32.h"
 #include "fis.h"
 #include "mtd.h"
 
@@ -85,6 +86,7 @@ static char *buf = NULL;
 static char *imagefile = NULL;
 static enum mtd_image_format imageformat = MTD_IMAGE_FORMAT_UNKNOWN;
 static char *jffs2file = NULL, *jffs2dir = JFFS2_DEFAULT_DIR;
+static char *tpl_uboot_args_part;
 static int buflen = 0;
 int quiet;
 int no_erase;
@@ -92,6 +94,7 @@ int mtdsize = 0;
 int erasesize = 0;
 int jffs2_skip_bytes=0;
 int mtdtype = 0;
+uint32_t opt_trxmagic = TRX_MAGIC;
 
 int mtd_open(const char *mtd, bool block)
 {
@@ -203,7 +206,7 @@ image_check(int imagefd, const char *mtd)
 
        magic = ((uint32_t *)buf)[0];
 
-       if (be32_to_cpu(magic) == TRX_MAGIC)
+       if (be32_to_cpu(magic) == opt_trxmagic)
                imageformat = MTD_IMAGE_FORMAT_TRX;
        else if (be32_to_cpu(magic) == SEAMA_MAGIC)
                imageformat = MTD_IMAGE_FORMAT_SEAMA;
@@ -472,12 +475,14 @@ mtd_write(int imagefd, const char *mtd, char *fis_layout, size_t part_offset)
        ssize_t r, w, e;
        ssize_t skip = 0;
        uint32_t offset = 0;
+       int buflen_raw = 0;
        int jffs2_replaced = 0;
        int skip_bad_blocks = 0;
 
 #ifdef FIS_SUPPORT
        static struct fis_part new_parts[MAX_ARGS];
        static struct fis_part old_parts[MAX_ARGS];
+       struct fis_part *cur_part = NULL;
        int n_new = 0, n_old = 0;
 
        if (fis_layout) {
@@ -487,6 +492,8 @@ mtd_write(int imagefd, const char *mtd, char *fis_layout, size_t part_offset)
 
                memset(&old_parts, 0, sizeof(old_parts));
                memset(&new_parts, 0, sizeof(new_parts));
+               if (!part_offset)
+                       cur_part = new_parts;
 
                do {
                        next = strchr(tmp, ':');
@@ -554,6 +561,17 @@ resume:
                lseek(fd, part_offset, SEEK_SET);
        }
 
+       /* Write TP-Link recovery flag */
+       if (tpl_uboot_args_part && mtd_tpl_recoverflag_write) {
+               if (quiet < 2)
+                       fprintf(stderr, "Writing recovery flag to %s\n", tpl_uboot_args_part);
+               result = mtd_tpl_recoverflag_write(tpl_uboot_args_part, true);
+               if (result < 0) {
+                       fprintf(stderr, "Could not write TP-Link recovery flag to %s: %i", mtd, result);
+                       exit(1);
+               }
+       }
+
        indicate_writing(mtd);
 
        w = e = 0;
@@ -576,6 +594,9 @@ resume:
                        buflen += r;
                }
 
+               if (buflen_raw == 0)
+                       buflen_raw = buflen;
+
                if (buflen == 0)
                        break;
 
@@ -587,6 +608,7 @@ resume:
 
                if (skip > 0) {
                        skip -= buflen;
+                       buflen_raw = 0;
                        buflen = 0;
                        if (skip <= 0)
                                indicate_writing(mtd);
@@ -610,6 +632,7 @@ resume:
                                w += skip;
                                e += skip;
                                skip -= buflen;
+                               buflen_raw = 0;
                                buflen = 0;
                                offset = 0;
                                continue;
@@ -638,7 +661,7 @@ resume:
                                        continue;
                                }
 
-                               if (mtd_erase_block(fd, e) < 0) {
+                               if (mtd_erase_block(fd, e + part_offset) < 0) {
                                        if (next) {
                                                if (w < e) {
                                                        write(fd, buf + offset, e - w);
@@ -675,6 +698,17 @@ resume:
                }
                w += buflen;
 
+#ifdef FIS_SUPPORT
+               if (cur_part && cur_part->size
+               && cur_part < &new_parts[MAX_ARGS - 1]
+               && cur_part->length + buflen_raw > cur_part->size)
+                       cur_part++;
+               if (cur_part) {
+                       cur_part->length += buflen_raw;
+                       cur_part->crc = crc32(cur_part->crc, buf, buflen_raw);
+               }
+#endif
+               buflen_raw = 0;
                buflen = 0;
                offset = 0;
        }
@@ -716,6 +750,18 @@ resume:
 #endif
 
        close(fd);
+
+       /* Clear TP-Link recovery flag */
+       if (tpl_uboot_args_part && mtd_tpl_recoverflag_write) {
+               if (quiet < 2)
+                       fprintf(stderr, "Removing recovery flag from %s\n", tpl_uboot_args_part);
+               result = mtd_tpl_recoverflag_write(tpl_uboot_args_part, false);
+               if (result < 0) {
+                       fprintf(stderr, "Could not clear TP-Link recovery flag to %s: %i", mtd, result);
+                       exit(1);
+               }
+       }
+
        return 0;
 }
 
@@ -765,12 +811,17 @@ static void usage(void)
        "        -l <length>             the length of data that we want to dump\n");
        if (mtd_fixtrx) {
            fprintf(stderr,
+       "        -M <magic>              magic number of the image header in the partition (for fixtrx)\n"
        "        -o offset               offset of the image header in the partition(for fixtrx)\n");
        }
        if (mtd_fixtrx || mtd_fixseama || mtd_fixwrg || mtd_fixwrgg) {
                fprintf(stderr,
        "        -c datasize             amount of data to be used for checksum calculation (for fixtrx / fixseama / fixwrg / fixwrgg)\n");
        }
+       if (mtd_tpl_recoverflag_write) {
+               fprintf(stderr,
+       "        -t <partition>          write TP-Link recovery-flag to <partition> (for write)\n");
+       }
        fprintf(stderr,
 #ifdef FIS_SUPPORT
        "        -F <part>[:<size>[:<entrypoint>]][,<part>...]\n"
@@ -828,7 +879,7 @@ int main (int argc, char **argv)
 #ifdef FIS_SUPPORT
                        "F:"
 #endif
-                       "frnqe:d:s:j:p:o:c:l:")) != -1)
+                       "frnqe:d:s:j:p:o:c:t:l:M:")) != -1)
                switch (ch) {
                        case 'f':
                                force = 1;
@@ -880,6 +931,14 @@ int main (int argc, char **argv)
                                        usage();
                                }
                                break;
+                       case 'M':
+                               errno = 0;
+                               opt_trxmagic = strtoul(optarg, 0, 0);
+                               if (errno) {
+                                       fprintf(stderr, "-M: illegal numeric string\n");
+                                       usage();
+                               }
+                               break;
                        case 'o':
                                errno = 0;
                                offset = strtoul(optarg, 0, 0);
@@ -896,6 +955,9 @@ int main (int argc, char **argv)
                                        usage();
                                }
                                break;
+                       case 't':
+                               tpl_uboot_args_part = optarg;
+                               break;
 #ifdef FIS_SUPPORT
                        case 'F':
                                fis_layout = optarg;