Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
ffu2img is a simple python script that converts Microsoft's FFU format to the standardized raw img format. IMG files are what you get from dd - just raw sectors. FFU involves a bunch of validation, verification, signing, sparse file expansion and apparently has deduplication features, although I haven't dug in and figured that out entirely. It was originally designed for imaging embedded devices like phones, but it seems that it will be available for all Windows devices now.
Two versions available, one tested with Python 2.7.9 the other tested with Python 3.4.3.
I naively thought I could get away with ignoring the block destination information supplied in the FFU and just outputting the raw sectors in the order that they exist in the FFU, but that did not work out. Even after adding in the block management, the output file didn't look right. Finally got it sorted today, and it looks to be working. I compared it to a disk image created with DISM/ImgMount, and it matches now.
Use by downloading the FFU image and running
>python ffu2img.py Flash.FFU
>python ffu2img.py Flash.FFU RPi.IMG
The first example will output Flash.IMG, while the second will output RPi.IMG. You can write the file to your device of choice using dd. I tested on an actual Pi2 and it boots fine. Please test and report your results, if possible.
Logs will be written to ffu2img.log on every run. They will overwrite any existing file of that name.
Interesting bit of info - the image doesn't have hardly any MBR, since the Pi2 uses an internal bootloader. No need for boot code.
The documentation kinda sucks...and it's prerelease, so they'll probably be changing it at some point. Which is weird, since FFU has been around since Windows Phone 7 from what I found on Windows Phone forums. If you want more FFU tools, look there...IMGMount came in handy, it creates a VHD from an FFU and mounts it.
We decode the first two parts of the FFU mostly so we can know how many bytes to seek to skip them. We do, however, use the chunk size. The part of the FFU file we care about is the third 'section', the store. It contains a header that details info about the store, validation entries and block entries. The validation entries are (surprisingly) used to validate the blocks, specifically during partial updates. I'm ignoring them entirely. The block entries tell you how to write out the blocks, which are in the final section of the FFU file, the payload. All we care about in the block entries in the RPi FFU is the destination address - as you iterate through the 128kb block chunks, you write them out to the destination supplied in the block entry. The destination isn't necessarily linear, it jumps around a bit, which is part of how you can inflate a 800MB file to 8GB. I'm pretty sure my unpack of the block entry structure is wrong, hopefully because the doc is wrong but more likely just cause I screwed up. I'll fix it eventually, probably after I get my hands on another FFU file to compare.