While working on improving WPInternals, more specifically the Spec A devices unlock process a challenge was presented to me.
For the unlock I’m working on, we needed to actually patch the EFIESP partition. With devices where we have mass storage, we actually did split EFIESP in half, the first half would be the original partition, and the second half would be the new one. But we had to swap those back in order to boot up Windows Phone with success. And to do that we had to make a backup from Mass storage mode. This worked well… but we had to use mass storage mode.
With Spec A devices, we’re not sure we have Mass storage mode on the phone. So how do we actually manage to flash a modified FAT32 partition, while keeping the original one, and the original partition offset in the GPT?
“With Spec A devices, we’re not sure we have Mass storage mode on the phone.
[…] While keeping […] the original partition offset in the GPT”
To solve that problem, we actually need to get a look at how a FAT32 partition is layered, more specifically its header.
The first sector of the EFIESP partition on phones contains the partition ID, which in this case is MSDOS5.0, partition size information, and the file system format. Every variant of FAT filesystems share the same header, so the format needs to be specified in the partition header as well. Some information about the bootsector is also present, with the actual bootsector payload beginning with the second sector.
This header is fully documented online, and you could probably find a better explanation than the one I would give about it. But here we will just focus on the main hack I used to achieve what we want.
The header contains a value at offset 0xE, which is the Reserved sector count, it’s an UInt16 variable, composed of two bytes which you can find here:
In this case our original partition has a Reserved sector count of 2 sectors. But hang on a minute, those two sectors are the header and the boot sector itself, what happens if we bump it to let’s say 0xFFFF?
Turns out reserved sector defines where the file allocation table begins in the partition. Bumping it to 0xFFFF would effectively allow us to have a secondary partition, without the header and bootsector, right in the middle of a 32MB EFIESP partition.
Turns out that’s what I did, while it worked great on paper, a second issue came later, while implementing the functionality into WPInternals. The flashing exploit WPInternals uses relies on FFU flashing technology in Flash App. I’ll skip all the details about this, but I’ll note down the main downside of this:
Flash app can only flash in chunks.
The issue here, we need to only write back the first sector, or two to be sure, we shouldn’t override the first chunk, as supposedly our file allocation table starts here… and that’s where the truth actually starts to shine. The first chunk of a FAT32 partition, even after the first two reserved sectors, is not the file allocation table. In fact, the file allocation table, truly takes place starting with the second chunk. The first chunk of a FAT32 partition, or any FAT filesystem, is actually always the same. I couldn’t make out much of the actual format, but it seems to just be an array of all ASCII characters that exist in a row, for real:
So that’s all good, we can actually flash the entire first chunk, albeit modified with our new reserved sector, and start flashing the new EFIESP at the 0xFFFF location, after the first sector defined in GPT!
And what about going back to the original partition? Well it’s as easy as writing the new partition hack, we just write back the original reserved sector count!
And here you have it, how to actually fit a new FAT partition, inside an existing FAT partition, while keeping a backup of the original FAT partition in the first half, and without ever reading it 🙂