lantiq: Tune the XWAY subtarget cflags
[openwrt/staging/blogic.git] / package / mtd / src / fis.c
index e774e62a6a305e1c28e86b410c12f132224a2c4c..f825f590c96a50141849d24c63b9d652ab146808 100644 (file)
@@ -1,3 +1,17 @@
+/*
+ * FIS table updating code for mtd
+ *
+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License v2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 #include <sys/mman.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -63,7 +77,7 @@ fis_open(void)
                goto error;
 
        fis_erasesize = erasesize;
-       desc = mmap(NULL, erasesize, PROT_READ|PROT_WRITE, MAP_SHARED, fis_fd, 0);
+       desc = mmap(NULL, erasesize, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, fis_fd, 0);
        if (desc == MAP_FAILED)
                goto error;
 
@@ -85,7 +99,7 @@ fis_validate(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
 
        desc = fis_open();
        if (!desc)
-               return 0;
+               return -1;
 
        for (i = 0; i < n_new - 1; i++) {
                if (!new[i].size) {
@@ -129,10 +143,12 @@ fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
        struct fis_image_desc *redboot = NULL;
        struct fis_image_desc *first = NULL;
        struct fis_image_desc *last = NULL;
+       struct fis_image_desc *first_fb = NULL;
+       struct fis_image_desc *last_fb = NULL;
        struct fis_image_desc *desc;
        struct fis_part *part;
        uint32_t offset = 0, size = 0;
-       char *end, *tmp;
+       char *start, *end, *tmp;
        int i;
 
        desc = fis_open();
@@ -142,6 +158,7 @@ fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
        if (!quiet)
                fprintf(stderr, "Updating FIS table... \n");
 
+       start = (char *) desc;
        end = (char *) desc + fis_erasesize;
        while ((char *) desc < end) {
                if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff))
@@ -153,9 +170,12 @@ fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
                if (!strcmp((char *) desc->hdr.name, "RedBoot"))
                        redboot = desc;
 
+               /* update max offset */
+               if (offset < desc->hdr.flash_base)
+                       offset = desc->hdr.flash_base;
+
                for (i = 0; i < n_old; i++) {
                        if (!strncmp((char *) desc->hdr.name, (char *) old[i].name, sizeof(desc->hdr.name))) {
-                               size += desc->hdr.size;
                                last = desc;
                                if (!first)
                                        first = desc;
@@ -166,13 +186,29 @@ fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
        }
        desc--;
 
-       if (desc == last) {
-               desc = fisdir;
+       first_fb = first;
+       last_fb = last;
+
+       if (first_fb->hdr.flash_base > last_fb->hdr.flash_base) {
+               first_fb = last;
+               last_fb = first;
+       }
+
+       /* determine size of available space */
+       desc = (struct fis_image_desc *) start;
+       while ((char *) desc < end) {
+               if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff))
+                       break;
+
+               if (desc->hdr.flash_base > last_fb->hdr.flash_base &&
+                   desc->hdr.flash_base < offset)
+                       offset = desc->hdr.flash_base;
+
+               desc++;
        }
+       desc--;
 
-       /* size fixup */
-       if (desc && (last->hdr.flash_base < desc->hdr.flash_base - last->hdr.size))
-                       size += (desc->hdr.flash_base - last->hdr.flash_base) - last->hdr.size;
+       size = offset - first_fb->hdr.flash_base;
 
 #ifdef notyet
        desc = first - 1;
@@ -188,7 +224,7 @@ fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
 
        last++;
        desc = first + n_new;
-       offset = first->hdr.flash_base;
+       offset = first_fb->hdr.flash_base;
 
        if (desc != last) {
                if (desc > last)