This is a patch for the mtd utility in order to address
the following issues:

- MTDREFRESH was defined as 23 whereas the actual value in the
  kernel is 24. Therefore refreshing the partitions during sysupgrade
  fails, which can lead to a corrupted root file system when sysupgrade
  tries to append the config files to the jffs2 partition
  The symptom is also reported by another user in ticket
  https://dev.openwrt.org/ticket/9267

  Change: Updated values from kernel header

- The FIS checksums where not populated.
  If compiled with checksum support RedBoot will ignore partitions
  without valid checksums. The current implementation of mtd sets
  the checksum to 0. Changing the RedBoot bootloader is not an
  option as changing the bootloader is very dangerous.

  Change: Checksum implemented (Redboot uses a simple sum)

- If you don't define new paritions (-F option) then an existing
  FIS partition is not updated

  Change: If -F option is not used and there is a FIS partition
          then it will be updated with the new length and checksum

Kind regards,
Tobias Waldvogel

Signed-off-by: Tobias Waldvogel <tobias.waldvo...@gmail.com>

Index: package/mtd/src/mtd-api.h
===================================================================
--- package/mtd/src/mtd-api.h   (revision 28079)
+++ package/mtd/src/mtd-api.h   (working copy)
@@ -85,17 +85,30 @@
        u_int32_t regionindex;
 };
 
-#define MEMGETINFO              _IOR('M', 1, struct mtd_info_user)
-#define MEMERASE                _IOW('M', 2, struct erase_info_user)
-#define MEMWRITEOOB             _IOWR('M', 3, struct mtd_oob_buf)
-#define MEMREADOOB              _IOWR('M', 4, struct mtd_oob_buf)
-#define MEMLOCK                 _IOW('M', 5, struct erase_info_user)
-#define MEMUNLOCK               _IOW('M', 6, struct erase_info_user)
+#define MEMGETINFO             _IOR('M', 1, struct mtd_info_user)
+#define MEMERASE               _IOW('M', 2, struct erase_info_user)
+#define MEMWRITEOOB            _IOWR('M', 3, struct mtd_oob_buf)
+#define MEMREADOOB             _IOWR('M', 4, struct mtd_oob_buf)
+#define MEMLOCK                        _IOW('M', 5, struct erase_info_user)
+#define MEMUNLOCK              _IOW('M', 6, struct erase_info_user)
 #define MEMGETREGIONCOUNT      _IOR('M', 7, int)
 #define MEMGETREGIONINFO       _IOWR('M', 8, struct region_info_user)
-#define        MEMREADDATA             _IOWR('M', 9, struct mtd_oob_buf)
-#define        MEMWRITEDATA            _IOWR('M', 10, struct mtd_oob_buf)
-#define MTDREFRESH                             _IO('M', 23)
+#define MEMSETOOBSEL           _IOW('M', 9, struct nand_oobinfo)
+#define MEMGETOOBSEL           _IOR('M', 10, struct nand_oobinfo)
+#define MEMGETBADBLOCK         _IOW('M', 11, __kernel_loff_t)
+#define MEMSETBADBLOCK         _IOW('M', 12, __kernel_loff_t)
+#define OTPSELECT              _IOR('M', 13, int)
+#define OTPGETREGIONCOUNT      _IOW('M', 14, int)
+#define OTPGETREGIONINFO       _IOW('M', 15, struct otp_info)
+#define OTPLOCK                        _IOR('M', 16, struct otp_info)
+#define ECCGETLAYOUT           _IOR('M', 17, struct nand_ecclayout_user)
+#define ECCGETSTATS            _IOR('M', 18, struct mtd_ecc_stats)
+#define MTDFILEMODE            _IO('M', 19)
+#define MEMERASE64             _IOW('M', 20, struct erase_info_user64)
+#define MEMWRITEOOB64          _IOWR('M', 21, struct mtd_oob_buf64)
+#define MEMREADOOB64           _IOWR('M', 22, struct mtd_oob_buf64)
+#define MEMISLOCKED            _IOR('M', 23, struct erase_info_user)
+#define MTDREFRESH             _IO('M', 24)
 
 #ifndef __KERNEL__
 
Index: package/mtd/src/fis.c
===================================================================
--- package/mtd/src/fis.c       (revision 28079)
+++ package/mtd/src/fis.c       (working copy)
@@ -89,6 +89,23 @@
        return NULL;
 }
 
+static void
+fis_update_checksum(struct fis_image_desc *desc)
+{
+       unsigned int checksum;
+       int i;
+
+       /* Calculate checksum */
+       checksum = 0;
+       i=(char*)&desc->crc - (char*)&desc->hdr;
+       while (i > 0) {
+               --i;
+               checksum += ((char*)desc)[i];
+       }
+       desc->crc.desc = checksum;
+}
+
+
 int
 fis_validate(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
 {
@@ -232,14 +249,14 @@
        for (part = new, desc = first; desc < first + n_new; desc++, part++) {
                memset(desc, 0, sizeof(struct fis_image_desc));
                memcpy(desc->hdr.name, part->name, sizeof(desc->hdr.name));
-               desc->crc.desc = 0;
-               desc->crc.file = 0;
 
                desc->hdr.flash_base = offset;
                desc->hdr.mem_base = part->loadaddr;
                desc->hdr.entry_point = part->loadaddr;
                desc->hdr.size = (part->size > 0) ? part->size : size;
                desc->hdr.data_length = desc->hdr.size;
+               desc->crc.file = 0;
+               fis_update_checksum(desc);
 
                offset += desc->hdr.size;
                size -= desc->hdr.size;
@@ -250,3 +267,40 @@
 
        return 0;
 }
+
+struct fis_image_desc *
+fis_find_entry(struct fis_image_desc *fis, const char* mtd)
+{
+       char *end = (char*)fis + fis_erasesize;
+
+       while ((char*)fis < end &&
+               fis->hdr.name[0] != 0x00 && fis->hdr.name[0] != 0xff) {
+               if (!strcmp((char*)fis->hdr.name, mtd))
+                       return fis;
+               fis++;
+       }
+
+       return NULL;
+}
+
+void
+fis_update_len(const char *mtd, ssize_t len)
+{
+       struct fis_image_desc *fis;
+
+       fis = fis_open();
+       if (!fis)
+               return;
+
+       fis = fis_find_entry(fis, mtd);
+       if (!fis)
+               goto done;
+
+       fprintf(stderr, "Updating data length in FIS table to 0x%08x\n", len);
+       fis->hdr.data_length = len;
+       fis_update_checksum(fis);
+       msync(fis_desc, fis_erasesize, MS_SYNC|MS_INVALIDATE);
+
+done:
+       fis_close();
+}
Index: package/mtd/src/mtd.c
===================================================================
--- package/mtd/src/mtd.c       (revision 28079)
+++ package/mtd/src/mtd.c       (working copy)
@@ -485,6 +485,9 @@
                if (fis_remap(old_parts, n_old, new_parts, n_new) < 0)
                        fprintf(stderr, "Failed to update the FIS partition 
table\n");
        }
+       else {
+               fis_update_len(mtd, w);
+       }
 #endif
 
        close(fd);
Index: package/mtd/src/fis.h
===================================================================
--- package/mtd/src/fis.h       (revision 28079)
+++ package/mtd/src/fis.h       (working copy)
@@ -10,5 +10,6 @@
 
 int fis_validate(struct fis_part *old, int n_old, struct fis_part *new, int 
n_new);
 int fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int 
n_new);
+void fis_update_len(const char *mtd, ssize_t len);
 
 #endif
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to