[HTC Wildfire S] no.human.being:
The areas are "protected" by not having them mapped as mtd devices. We therefore call the "protected" area "unmapped" area, as that's what it really is. However, you can map this area by issuing the "mtdparts=..." parameter to the kernel via Fastboot. How this works is explained here. However, for your devices, the parameters will be different. How we have done it is briefly explained here. It involved quite some amount of guesswork though. You'll have to "guess" the order of the partitions in memory, as the order doesn't correspond with the device numbers of the partitions. Once you've got the order right, it's more or less a straight-forward calculation. You start by the highest physical address and then go backwards. The "unmapped" area will be the area starting at physical 0x00000000 and ending at ("first physical address of 'mapped' memory in NAND" - 1).

Once you got the protected area mapped, you can interact with it almost like you can do with any other mtd partition. I say "almost", since the "out of band" area of the protected area is a bit special. Basically, all the pages that make up the protected area are also marked as "bad" (worn out). For this reason, any "normal" Linux/Android kernel will refuse to erase them. But more on this later. All operations that do not involve erasure are not affected by the pages being marked as "bad" so you can perfectly dump the contents of the protected area and analyze them.

I've created it, so I'm having the source. However, I'm not sure that it doesn't infringe intellectual property rights of ARM Ltd. or Google. I really don't want to get into trouble, so I'm currently not disclosing the source.

We map the SPL (HBOOT) as "mtd7" (as the "normal partitions" are "mtd0" to "mtd6" on our device, so "mtd7" is the first mtd device that's "unused", so we're using it for this purpose) via a kernel parameter passed via Fastboot. The "inject" utility reads the contents of "mtd7" into a buffer in RAM, patches the subprocedure checking the secu_flag status to always return 0 (= S-OFF) in this buffer, then calls the "flash_erase" tool from mtdutils to erase the SPL from the device NAND. Currently this fails, probably due to kernel-level restrictions, so the NAND does not get erased. Then we write the patched version back from our buffer to the mtd device. Currently this also fails, since the NAND is not in an erased state and overwriting NAND in-place results in undefined behaviour. Luckily the kernel seems to prevent writing to this area unless it is erased, so at least our "fwrite(...)" calls do not "damage" the SPL unless it was successfully erased from NAND before.

Erasing the NAND fails, since the blocks are marked as "bad" (worn out). The NAND only sustains about 10.000 erase-cycles per block. After that, it becomes "bad" and the transistors cease to hold their state. The flag basically tells the kernel that the blocks will become bad on the next erase cycle and therefore the kernel refuses to erase them. This check is performed by the mtd driver. Normally Android doesn't erase or write to the HBOOT area (it isn't even mapped as an mtd device and thus "invisible" under normal circumstances), only HBOOT does (e. g. when flashing an RUU).

HBOOT is it's own "operating system", so all they have to do is making HBOOT not (!!) check the "bad" (worn out) flag for the blocks it erases. This is the reason why HBOOT can write to the NAND, but we (on a Linux/Android based operating system) can't. Once we get a kernel built that does not perform this check in its mtd driver, we can erase the NAND holding the SPL and then we are done. Erasing the blocks will ultimately reset the "bad" flag and then we can write to them as we can do it with any other block.

I'm not using "nand_write", I'm just using an "fwrite(...)" on a file handle obtained by doing ...

fopen("/dev/mtd/mtd7", "wb")

... and the protected area has to be mapped as "mtd7" via parameters passed to the kernel via Fastboot.

The protection is enforced by the operating system kernel only. The hardware (MMU) can't enforce write-protection on the NAND. It's all done in software. If you don't believe me, look at the datasheets for the ARM 1136JS. The MSM7227 (this is the processor used in the WFS) is a replica of the ARM 1136

E

JS, but the datasheets for that one aren't open. However, the 1136JS should be very similar to the 1136EJS, so just take the datasheets for the 1136JS. Hardware NAND protection is not supported. It's just not there.

To get started on this, you'll have to find out how much "unmapped memory" is there on the phone. To get this, do a "cat /proc/mtd" on the phone while booted into stock ROM. Then add all the "size" information for the mtd partitions up. Then you'll have to know how large the physical address space is on the phone. On the WFS it's 0x00000000 to 0x1fffffff, so size of the physical address space is 0x20000000 bytes (all hexadecimal of course).

Then you take the size of the physical address space and subtract the sum of all "size"s of the mtd partitions. This gives us the values 0x026c0000 ("old" memory layout) or 0x02fc0000 ("new" memory layout, there seem to be two different memory layouts for the device). This is the amount of persistent (NAND) memory that is not mapped to any mtd partition ("unmapped memory") and therefore inaccessible when the device is booted normally.

We can map this memory by adding a "<size>@0x00000000(radio)" parameter to the kernel command line. Of course all the other "regular" partitions have to be passed before it, so you'll have to figure out the entire partition layout for the device. This maps the previously "unmapped" part as a new mtd device (in our case mtd7, as mtd0-6 are the "regular" partitions). We call the partition "radio", as it contains the Radio firmware of the device.

Once you have the memory mapped, you can dump its contents to a file on the SD card using "cat /dev/mtd/mtd7 > /sdcard/radio.img" (substitute "mtd7" with the correct mtd on your device). You then open the dump in a hex editor and look through it to find out where the HBOOT code begins. In our case this was very simple, as there's a lot of "unprogrammed NAND" holding the value 0xff between the Radio firmware and the HBOOT. Searching for the string "SHIP" may also help determining where the HBOOT starts, as it seems to always occur quite at the beginning of an HBOOT image. Once you know where the HBOOT starts, you can also look how large it is. In our case it's 512 KiB and I think it's the same for every device, but you might want to check it really is.

Last step is booting the kernel with only the HBOOT area mapped instead of the entire Radio firmware. You do this by passing the correct size of the HBOOT to the kernel and also the correct offset where it begins instead of 0x00000000. You can then dump the HBOOT code from your device's NAND to the SD card using "cat /dev/mtd/mtd7 > /sdcard/hboot.img". Then you can change whatever you want in the code (it's just a file). Afterwards, you do a "flash_erase -u /dev/mtd/mtd7" to erase the NAND area holding HBOOT. This step currently fails for us, as the mtd driver in the kernel refuses to erase the protected area. However, once you got the area erased, you can probably write your "modified HBOOT" image back using "cat /sdcard/hboot.img > /dev/mtd/mtd7".

The only thing the "inject" program really does is automate the reading, patching, erase and writeback process, doing it all in RAM instead of files on the SD card, performing version detection and safety checks to ensure that the correct instructions are modified and reading/writing directly via appropriate calls to the device handles instead of relying on tools like "cat" that weren't really designed for programming NAND.

Now that I've basically disclosed all our knowledge to you, could you possibly help us building a custom kernel that ignores the "bad" marker when erasing the NAND?