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