The last few days I’ve been toying with the possibility of installing OpenDingux directly on the internal NAND. What I’ve been doing so far, was to boot the kernel from USB, and have it load the root filesystem (an unmodified OpenDingux rootfs for the Dingoo A320) from the SD card. It worked fine, but I had to unplug the SD card everytime I wanted to boot the kernel (required for booting over USB), and I didn’t like the idea of having proprietary software on the NAND.
Problem was, to be able to install OpenDingux on the NAND, I had to format the NAND first. And lose my savestate of Pokémon Emerald, on which I spent more than 30 hours.
After figuring out the changes needed to the memory controller and the NAND controller, I was able to make a full dump of the NAND directly to the SD card, complete with Out-Of-Band (OOB) data (that’s the part that contains meta-data, like error correction codes). I then got the BCH (error correction) controller to work, so I could make a dump of the NAND without the OOB.
The problem is that a dump of the NAND is useless if you don’t know how the data is stored.
NAND flashes are very prone to wear. Each eraseblock (128 KiB of data) can be written only about 1000 times before it starts to fail. To counter this issue, the OS has something called a Flash Translation Layer (FTL). It is basically a table that maps logical eraseblocks to physical eraseblocks. With the FTL, if you store a MP3 on the NAND, your OS will see the file as a continuous stream of bytes till the end of the file, but in reality each block of 128 KiB will be stored at a pseudo-random address somewhere in the whole NAND. If you overwrite the MP3 with another one, the file’s data will appear at the same address, but the new data written will be stored in completely different eraseblocks. The FTL is then a mechanism to prevent the damage done to the eraseblocks by repeated writting to the same files.
Back to my problem. By hex-editing the NAND dump I figured that the filesystem used was FAT16; the problem was that the filesystem lies on top of a FTL, so it was cut in 128 KiB pieces scattered across the whole NAND. I had to figure out a way to map each physical eraseblock to a logical eraseblock. Sure enough, by spending some time hex-editing, I figured out that the first page of each eraseblock starting from address 0x20000 had incorrect error-correction data in its OOB area. By looking closer, I could figure out that one 32-bit word contained a different number for each erase block: most likely that value corresponded to the logical erase block that was mapped to that physical erase block. And sure enough, after modifying the FTL driver that was used on the Dingoo A320 to fit the Retromini’s NAND, I could access the files and save my precious Pokémons!
Now, to finish this post, I have a good news and a bad news.
I’ll start with the good one: I cleaned and pushed my jz-4.18-retromini branch on Github. It contains all the work I did so far on the Retromini, including the FTL driver. By combining all the information I’ve written in this blog so far, it should be possible for other people to boot their own kernels.
The bad news: I know that will deceive some, but I think I’m done with this for this year. I’m about to start a 1800km walk, then probably travel in Spain and South America for a bit. My Retromini will stay at home, like my laptop.
Till next time!