This patch fixes the issue I was having with sysupgrade failing due to bad nand 
flash blocks.

It uses the MEMGETBADBLOCK ioctl to determine if the block is bad before 
attempting to erase / write it.

Thanks,
Matt

Index: package/system/mtd/src/mtd.c
===================================================================
--- package/system/mtd/src/mtd.c         (revision 38980)
+++ package/system/mtd/src/mtd.c      (working copy)
@@ -107,6 +107,19 @@
               return fd;
}
+int mtd_block_is_bad(int fd, int offset)
+{
+             int r;
+             loff_t o = offset;
+             r = ioctl(fd, MEMGETBADBLOCK, &o);
+             if (r < 0)
+             {
+                             fprintf(stderr, "Failed to get erase block 
status\n");
+                             exit(1);
+             }
+             return r;
+}
+
int mtd_erase_block(int fd, int offset)
{
               struct erase_info_user mtdEraseInfo;
@@ -236,10 +249,17 @@
               for (mtdEraseInfo.start = 0;
                                mtdEraseInfo.start < mtdsize;
                                mtdEraseInfo.start += erasesize) {
-
-                              ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
-                              if(ioctl(fd, MEMERASE, &mtdEraseInfo))
-                                              fprintf(stderr, "Failed to erase 
block on %s at 0x%x\n", mtd, mtdEraseInfo.start);
+                             if (mtd_block_is_bad(fd, mtdEraseInfo.start))
+                             {
+                                             if (!quiet)
+                                                             fprintf(stderr, 
"\nSkipping bad block at %u   ", mtdEraseInfo.start);
+                             }
+                             else
+                             {
+                                             ioctl(fd, MEMUNLOCK, 
&mtdEraseInfo);
+                                             if(ioctl(fd, MEMERASE, 
&mtdEraseInfo))
+                                                             fprintf(stderr, 
"Failed to erase block on %s at 0x%x\n", mtd, mtdEraseInfo.start);
+                             }
               }
                close(fd);
@@ -324,6 +344,7 @@
               ssize_t skip = 0;
               uint32_t offset = 0;
               int jffs2_replaced = 0;
+             int skip_bad_blocks = 0;
 #ifdef FIS_SUPPORT
               static struct fis_part new_parts[MAX_ARGS];
@@ -466,10 +487,22 @@
                               /* need to erase the next block before writing 
data to it */
                               if(!no_erase)
                               {
-                                              while (w + buflen > e) {
+                                             while (w + buflen > e - 
skip_bad_blocks) {
                                                               if (!quiet)
                                                                               
fprintf(stderr, "\b\b\b[e]");
+                                                             if 
(mtd_block_is_bad(fd, e))
+                                                             {
+                                                                             
if (!quiet)
+                                                                               
              fprintf(stderr, "\nSkipping bad block at %u   ", e);
+
+                                                                             
skip_bad_blocks += erasesize;
+                                                                             e 
+= erasesize;
+
+                                                                             
// Move the file pointer along over the bad block.
+                                                                             
lseek(fd, erasesize, SEEK_CUR);
+                                                                             
continue;
+                                                             }
                                                                if 
(mtd_erase_block(fd, e) < 0) {
                                                                               
if (next) {


From: openwrt-devel [mailto:openwrt-devel-boun...@lists.openwrt.org] On Behalf 
Of Matthew Redfearn
Sent: 29 November 2013 11:59
To: openwrt-devel@lists.openwrt.org
Subject: [OpenWrt-Devel] sysupgrade fails due to bad nand flash blocks

Hi all,
I have a problem with sysupgrade failing prematurely because my nand flash 
contains bad blocks. This results in an incomplete rootfs image in flash upon 
reboot from sysupgrade. I am running an attitude adjustment derivative (svn 
r35400) for custom hardware.
Uboot / the kernel seem to deal with bad flash blocks correctly, this only 
occurs when using mtd via sysupgrade.

This is what I see:

# sysupgrade openwrt-lpc32xx-JNRD6040--jffs2-sysupgrade.bin
Saving config files...
Sending TERM to remaining processes ... syslogd klogd hotplug2 ubusd netifd 
mrd6 dbus-daemon dnsmasq avahi-daemon
Sending KILL to remaining processes ...
Switching to ramdisk...
Performing system upgrade...
Unlocking firmware ...

Writing from <stdin> to firmware ...  [e][  502.560000] nand_erase_nand: 
attempt to erase a bad block at page 0x00002080
Failed to erase block
Upgrade completed
Rebooting system...
[  502.580000] Restarting system.

I found this ticket from a while ago that seems to cover this:

https://dev.openwrt.org/ticket/11749

Looking at the latest version of mtd in trunk I can't see anything to address 
this issue - is this something that is not that common and so hasn't been 
observed on other hardware?

Thanks,
Matt


Attachment: mtd-bad-nand-blocks-trunk.patch
Description: mtd-bad-nand-blocks-trunk.patch

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to