Page 1 of 1

Pacemaker firmware format

Posted: Fri Nov 16, 2012 1:42 am
by ubergeek
Pacemaker firmware files (file format, extraction and modification)

The firmware files available on this site are generally .pfw files (pacemaker firmware). The .pfw file may also be zipped, we will assume that this is not the case. One easy way to tell is to look at the file size, unzipped pfw files will always be 51200512 bytes. If it is zipped, simply

Code: Select all

unzip -d ./extracted_dfw_1412 dfw_14142.pfw
The pfw file is basically a filesystem for an embedded linux system. It is in the ext3 format, and can be mounted on linux. All commands here are for linux, and generally Ubuntu/Debian specific. It may be possible to do the following in Windows, though I haven't tried. Further, I've found in analysing an embedded linux system, it is generally easy to do it in linux.

Extracting the firmware:

Code: Select all

sudo mkdir /mnt/pm
sudo mount dfw_14142.pfw /mnt/pm -t ext3 -o loop
Once mounted, there is another filesystem stored within a file. This filesystem is a cramfs image located at /mnt/pm/boot/cramfs.little
This requires additional tools to extract which can be done as follows

Code: Select all

sudo apt-get install cramfsprogs fusecram
Then you can either extract the filesystem

Code: Select all

mkdir ./cramfs
cramfsck -v -x ./cramfs /mnt/pm/boot/cramfs.little
Or mount it using fuse

Code: Select all

sudo mkdir /mnt/cramfs
sudo mount /mnt/pm/boot/cramfs.little /mnt/cramfs -t cramfs -o loop
pfw file structure:

The ext3 file system is actually 51200000 bytes:

Code: Select all

$ dumpe2fs /dev/loop0
dumpe2fs 1.41.9 (22-Aug-2009)
...
Block count:              50000
Block size:               1024
...
This shows that the ext3 filesystem thinks it is 50000*1024 bytes = 51200000 bytes, whereas the file size is 51200512 bytes. The extra 512 bytes look something like

Code: Select all

$ dd if=dfw_14142_original.pfw bs=1 count=512 skip=51200000 | hexdump -C
512+0 records in
512+0 records out
512 bytes (512 B) copied, 0.0256741 s, 19.9 kB/s
00000000  30 32 30 31 30 39 64 66  77 5f 31 34 31 34 32 00  |020109dfw_14142.|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000080  00 00 00 00 30 35 31 34  31 34 32 00 00 00 00 00  |....0514142.....|
00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000a0  00 00 00 00 30 35 31 34  31 34 32 00 00 00 00 00  |....0514142.....|
000000b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000c0  00 00 00 00 30 35 31 32  38 33 38 00 00 00 00 00  |....0512838.....|
000000d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000e0  00 00 00 00 32 34 61 62  39 64 34 36 65 66 2d 34  |....24ab9d46ef-4|
000000f0  38 37 63 2d 34 30 61 35  2d 62 30 37 33 2d 31 39  |87c-40a5-b073-19|
00000100  61 36 66 30 37 63 32 33  63 38 30 30 00 00 00 00  |a6f07c23c800....|
00000110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 32 30  |..............20|
000001e0  63 62 32 37 64 61 35 38  36 65 32 64 35 66 37 38  |cb27da586e2d5f78|
000001f0  61 61 38 37 37 63 38 34  66 32 62 66 32 33 36 33  |aa877c84f2bf2363|
The fields are of the form [length (hex)] + [data]

Code: Select all

length, value, comment
02, 01, ?
09, dfw_14142, filename?
05, 14142, firmware version
05, 14142, software version
05, 12838, bootloader version?
24, ab9d46ef-487c-40a5-b073-19a6f07c23c800, UID?
20, cb27da586e2d5f78aa877c84f2bf2363, md5 hash
We see the hash at the end (cb27da586e2d5f78aa877c84f2bf2363). Turns out that this hash is an md5 of everything up to the last 34 bytes of the pfw file.

For proof we extract 51200478 = 51200512 - 34 bytes from the pfw file and hash it:

Code: Select all

$ dd if=dfw_14142_original.pfw of=dfw_14142_original_30d41de.pfw bs=1 count=51200478
51200478+0 records in
51200478+0 records out
51200478 bytes (51 MB) copied, 1414.49 s, 36.2 kB/s
$ md5sum dfw_14142_original_30d41de.pfw
cb27da586e2d5f78aa877c84f2bf2363  dfw_14142_original_30d41de.pfw
If you wanted to recover the pfw file (or modify it and recreate a hash) you'd do

Code: Select all

$ HASH=`md5sum dfw_14142_original_30d41de.pfw | awk '{print $1}'`
$ echo -n "20"$HASH >> dfw_14142_original_30d41de.pfw
Boot process:

The PMD boot process is summarised as follows

Code: Select all

redboot.bin
zImage
cramfs.little
- /etc/rc.d
- /etc/rc.d/init.d/pm-setup
   - /usr/local/bin/pwrLauncherApp
      - /usr/local/bin/pwrApplication 
         - /bin/pmplayer
The redboot bootloader is the first thing that the processor passes control to. It then decompresses the kernel image in zImage which mounts the cramfs filesystem.

From there its a relatively standard linux boot process that runs scripts in /etc/rc.d/init.d

Of direct interest is the pm-setup script which launches pwrLauncherApp. pwrLauncherApp launches pwrApplication and pmplayer. pwrApplication is definitely the one that does checking and installation of firmware updates via pfw files.

Re: Pacemaker firmware format

Posted: Sat Nov 17, 2012 12:50 am
by Sox
Thanks for taking thr time to write this up.

Now that you/we know this, in what way do you imagine we can use this to our advantage?