NAND

In the sunxi world, NAND (a type of flash memory) signifies the on board flash memory of a sunxi device. Our main u-boot version currently does not support booting from NAND and an altered allwinner version needs to be used instead.

WARNING: Currently, linux-sunxi kernel support allwinner specific NAND format, but in recent time that format will be obsolute due ongoning mainlining process.

= Background =

Our SoCs have a very specific boot process. First it executes a tiny on chip rom (BROM) which then checks the buttons for FEL mode and then starts checking the various storage options for a valid boot signature at the right location.

There is no real difference between NAND and an SD-card apart from the fact that directly attached flash use the Sunxi NAND controller directly while SD-Cards come with a standard interface and an embedded controller. The sunxi nand controller is harder to implement than the sunxi sd-card controller, and the sample code provided by allwinner is rather large (and shared between U-boot and the kernel).

Then there is the NAND hw randomizer that gets in the way. Allwinner uses one setting for the BROM and the second boot stage (boot0/SPL), and another setting for normal use. With this setup, it is currently not implemented to access both bits at the same time. This currently provides another barrier for implementation, as one first needs to be able to read/write this area. While this is not beyond fixing, these are quite a few hoops to jump through.

As a result of the above, we have to use the existing second and third stages of the allwinner nand boot process, and we need to use nand-part for partitioning. If we had proper u-boot support, we would not need any of that.

= Installing to NAND =

There is a nice, full howto available which explains how to install and boot from NAND.

= nand-part =

There is a utility which is part of sunxi-tools, called nand-part. It has many many issues:


 * The licensing is all muddled up. The author is not chinese, but the main file which only carries his copyright has chinese comments.
 * Barely passes as C-code. There are very few C style comments, and return values are 1 for success and 0 for failure.
 * Doesn't care about the size of the block device (how hard would it have been to check BLKGETSIZE64), and allows the creation of partition tables which are not contained within the bounds of the block device.
 * There are two known versions of allwinner nand partition tables. Instead of checking the magic and version fields, the code is fully duplicated but with different structs, and both versions of the code get run to see which one sticks. This needs to have the two versions of the structs living side by side (version the structure names!).

It needs a day or so of work by a proper coder.

As an extra, the format of the allwinner nand partitioning is really simple. It should be easy to write a simple interactive user interface like fdisk has, as the amount of options are really limited. m, p, n, d, v, w, q for the standard uses, and f for toggling a mode which gives the ability to alter the first partition and for changing the partitioning version.

This utility can be redeveloped without hardware. A dump of the nand of a machines first MB, plus a dd from /dev/zero, can be presented as a loop device. For an example of this, check this.

nand-part output
Below is the typical output of the nand partitioning of a Mele A1000.

check partition table copy 0: mbr: version 0x00000100, magic softw311 OK check partition table copy 1: mbr: version 0x00000100, magic softw311 OK check partition table copy 2: mbr: version 0x00000100, magic softw311 OK check partition table copy 3: mbr: version 0x00000100, magic softw311 OK mbr: version 0x00000100, magic softw311 9 partitions partition 1: class =         DISK, name =       BOOTFS, partition start =     2048, partition size =    32768 user_type=0 partition 2: class =         DISK, name =      LROOTFS, partition start =    34816, partition size =    65536 user_type=2 partition 3: class =         DISK, name =    LSYSTEMFS, partition start =   100352, partition size =   524288 user_type=2 partition 4: class =         DISK, name =      LDATAFS, partition start =   624640, partition size =  3145728 user_type=2 partition 5: class =         DISK, name =         MISC, partition start =  3770368, partition size =     2048 user_type=2 partition 6: class =         DISK, name =  LRECOVERYFS, partition start =  3772416, partition size =    65536 user_type=2 partition 7: class =         DISK, name =     LCACHEFS, partition start =  3837952, partition size =   262144 user_type=2 partition 8: class =         DISK, name =          env, partition start =  4100096, partition size =     4096 user_type=0 partition 9: class =         DISK, name =        UDISK, partition start =  4104192, partition size =        0 user_type=0 check partition table copy 0: mbr: version 0x00000100, magic softw311 OK check partition table copy 1: mbr: version 0x00000100, magic softw311 OK check partition table copy 2: mbr: version 0x00000100, magic softw311 OK check partition table copy 3: mbr: version 0x00000100, magic softw311 OK mbr: version 0x00000100, magic softw311 9 partitions partition 1: class =         DISK, name =       BOOTFS, partition start =     2048, partition size =    32768 user_type=0 partition 2: class =         DISK, name =      LROOTFS, partition start =    34816, partition size =    65536 user_type=2 partition 3: class =         DISK, name =    LSYSTEMFS, partition start =   100352, partition size =   524288 user_type=2 partition 4: class =         DISK, name =      LDATAFS, partition start =   624640, partition size =  3145728 user_type=2 partition 5: class =         DISK, name =         MISC, partition start =  3770368, partition size =     2048 user_type=2 partition 6: class =         DISK, name =  LRECOVERYFS, partition start =  3772416, partition size =    65536 user_type=2 partition 7: class =         DISK, name =     LCACHEFS, partition start =  3837952, partition size =   262144 user_type=2 partition 8: class =         DISK, name =          env, partition start =  4100096, partition size =     4096 user_type=0 partition 9: class =         DISK, name =        UDISK, partition start =  4104192, partition size =        0 user_type=0