NAND Flash

From NAS-Central Netgear Wiki
Jump to: navigation, search

ReadyNAS Duo & NV+ are both equipped with a 64MByte HYNIX NAND flash storing the boot loader & firmware image.

The flash is partitioned in two MTD partitions.

The first partition contains two copies of the iboot boot loader, a "backup" in the first two blocks (32K), normally unaccessible from Linux due to not having proper ECC info, and the active version in the next two blocks.

The second contains the firmware image as-is, encrypted and all.

To access these simply create the mtdblock0 and mtdblock1 device nodes in /dev. The kernel allows both read and write access to both, but don't mess with mtdblock0 unless you know exactly what you are doing as this can easily brick your device.. (it contains the iboot boot loader, who is responsible for general startup including the TFTP boot emergency recovery...)


The NAND chip hardware seem to be wired like follows:

x8 NAND chip

CE is controlled by some PCI control line. See SET/CLRNCE code below (quote from padre_nand_flash.c in linux-2.4 sources)

CLE and ALE is controlled by address lines 0x10000 and 0x20000. For some reason the generic nand driver is handpatched to map this instead of doing it by adjusting the I/O address in the hwcontrol function..


CE:

        case NAND_CTL_SETNCE:
                tmp = readl(PADRE_PCI_FEATURE);
                tmp |= ( 2<<9);
                tmp &= ~PADRE_PCI_FEATURE_PCION;

                writel(tmp, PADRE_PCI_FEATURE);
                break;
        case NAND_CTL_CLRNCE:
                tmp = readl(PADRE_PCI_FEATURE);
                tmp &= ~( 2<<9);
                tmp |= PADRE_PCI_FEATURE_PCION;
                writel(tmp, PADRE_PCI_FEATURE);
                break;

CLE:

    if(g_sys_type == SYSTEM_TYPE_PZERO)
    {
        NAND_IO_ADDR += 0x10000;
    }

    /* Begin command latch cycle */
    this->hwcontrol (mtd, NAND_CTL_SETCLE);

ALE: (follows the code above, so effectively base + 0x20000 which clears CLE and sets ALE)

    if(g_sys_type == SYSTEM_TYPE_PZERO)
    {
        NAND_IO_ADDR += 0x10000;
    }

    /* Set ALE and clear CLE to start address cycle */
    this->hwcontrol (mtd, NAND_CTL_CLRCLE);

    if (column != -1 || page_addr != -1) {
        this->hwcontrol (mtd, NAND_CTL_SETALE);


The generic nand driver (nand.c) used in the Intrant 2.6 kernel is actually a copy of the 2.4 NAND driver with "PADRE" handpatching, just updated to work in 2.6 and some small additions in ECC & badblock management. Very patchy instead of making proper use of the MTD NAND hardware interface.. Exact base kernel version unknown, probably using updated sources from the MTD. Latest timestamp in the file is "06-04-2003 tglx: fix compile errors and fix write verify problem for"..

To read the first stage iboot in the first two blocks of the NAND the driver needs to be told to ignore ECC. This can be done by using the vpd_override=2 module flag. Get a copy of padre_nand_flash.ko either from the initrd or GPL source tree, then

   rmmod padre_nand_flash
   modprobe padre_nand_flash vpd392_override=2
   cat /dev/mtd0 >/tmp/mtd0.img


Layout in my flash is

0x000000 - 0x0001ff  unused
0x000200 - 0x003fff  initial iboot loader
0x004000 - 0x0080ff  Unused
0x008100 - 0x0081ff  various system settings
0x008200 - 0x00bfff  unused
0x00c000 - 0x013fff  main iboot loader
0x014000 - 0x0fffff  unused