Wednesday, December 29, 2010

PLF File Format

A few weeks ago i bought an A.R. Drone from Parrot. This quadcopter is controlled over WLAN and uses an embedded Linux on an ARM chipset.

Altough it is possible via FTP / Telnet to modify the file system, i was intreseted in the flash file format. So I analyzed the available firmware.

I was quite successful athough there are still some unkown fields left.

Fileheader:
typedef struct sPLFFile
{
  u32 dwMagic; 
  u32 dwHdrVersion;
  u32 dwHeaderSize;
  u32 dwEntryHeaderSize;
  u32 uk_0x10;
  u32 uk_0x14;
  u32 uk_0x18;
  u32 uk_0x1C;
  u32 uk_0x20;
  u32 dwVersionMajor;
  u32 dwVersionMinor;
  u32 dwVersionBugfix;
  u32 uk_0x30;
  u32 dwFileSize;
}

The fields have the following meaning:

  • dwMagic: MagicCode of the file. Must be 0x21464C50
  • dwHdrVersion: Version of the header struct. Only seen with 0xB or 0xA
  • dwHeaderSize: Size of the file header. Must be 0x38.
  • dwEntryHeaderSize: Size of the section header. Must be 0x14.
  • uk_0x10: Currently unkown. Maybe some Type. Seen with 0x2
  • uk_0x14: Currently unkown. Maybe an EntryPoint. Seen with 0x0
  • uk_0x18: Currently unkown. Maybe the Device Type. Seen with 0x4
  • uk_0x1C: Currently unkown. Maybe the Model Number. Seen with 0x4E
  • uk_0x20: Currenlty unkown. Seen with 0x20
  • dwVersionMajor: Major version of this firmware
  • dwVersionMinor: Minor version of this firmware
  • dwVersionBugfix: Bugfix version of this firmware
  • uk_0x30: Curently unkown
  • dwFileSize: Size of the file.



After the header the sections follow. Each section starts with the following header.
typedef struct sPLFEntryTag
{
  u32 dwSectionType;
  u32 dwEntrySize;
  u32 dwCRC32;
  u32 uk_0x0C;
  u32 dwUncompressedSize;
}

The fields have the following meaning:
  • dwSectionType: Type of the section.

    0x00: unkown
    0x03: probably the bootloader
    0x07: unkown
    0x09: Filesystem action/content
    0x0b: Configuration Data (Mounting, creation of partitions)
    0x0c: Installer (contains another PLF file)
  • dwEntrySize: Size of the section (excluding header size)
  • dwCRC32: CRC-32 of the content and EntrySize
  • uk_0x0C: Currently unkown. Seems to be the address where to load the section to
  • dwUncompressedSize: If > 0, the content of this entry is compressed with gzip format. The value represents the uncompressed size of the entry.
The meaning of each section depends on dwSectionType.

0x09 - File system content
Each section represents one entry on the file system. It first starts with the null-terminated filename (variable length). After this name, the following header is placed:

typedef struct sFileEntryTag
{
  u32 dwFlags;
  u32 uk_0x04;
  u32 uk_0x08;
} sFileEntry;

  • dwFlags: Flags of the file entry. Encodes the type of the entry and the access rights.

    bit00-11: Rights of the file. Its the same as you would use for chmod. E.g. 0755 -> 0x1ED
    bit12-15: Type of the file entry:
    • 0x04: mkdir. No more data follows after the header.
    • 0x08: write. The file content follows after the header.
    • 0x0A: symlink. The target of the link follows after the header.
  • uk_0x04: Currently unkown. Seems to be either the UID or GID.
  • uk_0x08: Currently unkown. Seems to be either the UID or GID.
0x0b - Configuration data
This section contains informations about mounting, truncating and creating partitions. There is an old and a new version.

Old version (starts with "/mnt"):
32 bytes unkown. Then a u32 with some unkown_count follows. Then unkown_count*8 bytes follows. Then a u32 with the number of entries follows. Afterwards, the entries follow.

New version (does not start with "/mnt"):
typedef struct sPartitionSectionTag
{
  u32 dwTblVersion;
  u32 dwVersionMajor;
  u32 dwVersionMinor;
  u32 dwVersionBugfix;
  u32 uk_0x10;
  u32 uk_0x14;
  u32 uk_0x18;
  u32 uk_0x1C;
  u32 uk_0x20;
  u32 dwNumEntries;
} sPartitionSection;

  • dwTblVersion: Seems to be the version of this "partition table". 
  • dwVersionMajor: Major version
  • dwVersionMinor: Minor version
  • dwVersionBugfix: Bugfix version
  • uk_0x10 - uk_0x20: Unkown
  • dwNumEntries number of partition entries
For both, new and old version, the entries follow directly after the header. Each entries had the following format:

typedef struct sPartitionEntryTag
{
  u16 wDevice;
  u16 wVolumeType;
  u16 wVolume;
  u16 uk_0x06;
  u32 dwVolumeSize;
  u32 wVolumeAction;
  u8  cVolumeName[32];
  u8  cMountName[32];
} sPartitionEntry;

  • wDevice: Device number
  • wVolumeType: Volume type.
    • 0x0: RAW - no file system is available on this device
    • 0x1: STATIC - A filesystem is available but will not change (e.g. for the boot partitions)
    • 0x2: DYNAMIC - A filesystem is availalbe and can be changed 
  • wVolume: Volume number
  • uk_0x06: Unkown
  • dwVolumeSize: Size of the volume. Only to be used for wVolumeAction=2
  • wVolumeAction
    • 0x0: mount. Only for wVolumeType=2! -> mount /dev/ubi__
    • 0x1: truncate and mount -> Truncates the partition and mounts it afterwards
    • 0x2: create partition -> will call ubimkvol

... to be continued ...

Feel free to leave your comments!

1 comments:

  1. Hello.

    How could you disassemble that .plf file? I want to learn about this file type, for editing my Parrot Car Kit.

    ReplyDelete