Vous êtes sur la page 1sur 9

The Fortis IRD Format

Version 1.1
December 2nd 2011
smogm
(translated into English by Audioniek)

Originally published in German by:

GROUP LEViATHAN
http://www.leviathan-hd.com
smogm GROUP LEViATHAN

Contents
1 The IRD format ................................................................................3
1.1 Testing the IRD Container ........................................................................... 3
1.2 The flash process......................................................................................... 4
2 Partition types .................................................................................6
3 Logical flash layout ........................................................................7
4 Further checks by the bootloader .................................................8
4.1 SquashFS check .......................................................................................... 8
4.2 The Application backup ................................................................................ 8
4.3 Circumventing the SquashFS check ............................................................ 8
4.4 Circumventing the Application backup ......................................................... 9

The Fortis IRD format Page 2


smogm GROUP LEViATHAN

1 The IRD format


The Korean STB producer Fortis has developed the IRD format, a variable container
format in which the flash partitions are embedded as images.
Together with the modified uboot boot loader which is present in the receiver from
new, this forms a comfortable firmware update system for the end user.

The only thing an end user must do is copy the IRD container file onto a FAT32
formatted USB stick, and attach it to the receiver. When the user presses and holds
a certain key on the front panel while powering up the receiver (on most models it is
the channel up key), the boot loader will start in update mode and tries to find files on
the USB stick that have the extension .ird or .IRD. The first file it detects will be
copied into the local work memory, after which it will undergo an integrity test.

1.1 Testing the IRD Container


During the test a few basic integrity features are checked. Each IRD container has a
header at its beginning holding information about the data that follow in the
container. In addition the header holds a unique model code that identifies the
receiver model the container is intended for. The code is usually referred to as the
reseller ID.
When the IRD container was created a CRC16 checksum over the header data was
calculated and added to the container at the end of the header part. This will protect
the IRD container from easy modification and data transmission errors.
The boot loader will read the header and calculate the CRC16 of its data. It then
compares the calculated CRC16 with the value read from the container. If the
checksums match, the bootloader will proceed to the next step; if they do not an
error code 0x13 is displayed on the front panel and the process is aborted.

Every Fortis reseller will be allotted a unique reseller ID for each Fortis model range
he sells. The reseller ID is hard coded into the bootloader. The next test is a check of
the reseller ID: the one hardcoded in the bootloader must be the same as the one in
the IRD container header. If this is the case the process will be taken to the next
step; if not an error code 0x10 is displayed on the front panel, and the process is
aborted (note from translator: the reseller ID check is performed when the entire IRD
file has been read in).

The Fortis IRD format Page 3


smogm GROUP LEViATHAN

1.2 The flash process


After the IRD header the partitions follow. When the container was created these
were divided up in blocks of possibly equal size (in practice 0x7FFA is used), and
then compressed using zlib deflate.
The compression result is then added to a 32 bit header that holds the partition type
(16 bits, 2 bytes) and the original length of the block (also 16 bits or 2 bytes).
Then a CRC16 checksum is calculated over the header and the compressed block,
that is added to a second header that also holds the compressed length of the data
block that follows it (and that is actually present in the IRD container). With this data,
the bootloader can calculate the start position of the next block.

The sequence is repeated until the end of the partition image is reached.

The Fortis IRD format Page 4


smogm GROUP LEViATHAN

The boot loader simply reverses the process described above. First the 16 bit
compressed length is read, and then the CRC16 that follows it.
The next word in the container is the partition type. This is checked for validity (must
be 0 through 9). If a type other than that is found, the process is aborted and the
front panel shows an error code 0x14 (note: added by translator).
After the partition type, the number of uncompressed bytes is read.

The process is continued by reading the compressed length number of bytes from
the container, and a CRC16 is calculated over them. The calculated checksum is
then compared with the CRC16 read from the container. When both checksums
match, and the uncompressed length is larger than the compressed length, the block
is decompressed (using zlib inflate) and stored in RAM.
In case the CRC16 checksums differ, the process is aborted and error code 0x13 is
displayed on the front panel of the receiver. In case the compressed length and the
uncompressed length were the same, the block is merely copied into RAM.

This way, the boot loader rebuilds the partition image in RAM, block by block. This
will continue until either the end of the IRD container is reached, or the next header
contains a different partition type, indicating the start of the next partition.

Next, a size check is done to determine whether or not the partition just read will fit
its designated flash memory block. If it does, the boot loader starts handling the next
partition if there is one; if it does not, the process is aborted and an error 0x11 is
displayed.
If a new partition type is detected, the process is repeated for that partition, until the
entire IRD container is read. (Note from translator: this is what actually happens; the
original text explains that after reading one partition is it flashed immediately before
the next partition is handled.)

The IRD header of the complete container also holds the total number of blocks
present in the entire container. When the reading process is complete, that number
is checked as well. This way, the bootloader can determine the IRD container is
indeed complete. When a mismatch is found, the process again is aborted and error
code 0x13 is displayed on the front panel of the receiver.
Two final tests are done before the actual flashing begins. The first is a check of
reseller ID mentioned above. The second is a check of the IRD version number, also
contained in the header. If an unknown number is found the process again aborts
with errorcode 0x15 shown on the front panel.

After all these checks the bootloader will start flashing the partitions one by one. The
order in which they are flashed depends on the receiver model; most older receivers
flash the partitions in the order in which they are present in the IRD container.

The Fortis IRD format Page 5


smogm GROUP LEViATHAN

2 Partition types
The flash layout is embedded in the boot loader. With most receiver models the flash
layout is fixed, that is, each partition is flashed at a fixed, predetermined address.
There are ten different partitions, identified by their unique ID number (note from
translator: one can argue that the IRD header has partition type 0x10, but holds no
partition data).
The chronological order of the partition ID’s does not reflect the order they are stored
in flash memory.

ID Name
0 Bootloader
1 Application
2 Configuration - first 256 kbyte
3 Configuration - next 256 kbyte
4 Configuration - next 128 kbyte
5 Configuration - next 128 kbyte
6 Kernel
7 Device
8 Root
9 User

Early Fortis receivers with 32 Mbyte of flash memory can only flash 26.75 Mbyte of
the total flash memory available. This is caused by the fact that the Application
partition is mirrored in flash. The Application (will be called “App” in the remainder of
the text) uses 5 Mbyte plus another 5 Mbyte for its mirror. The latter flash area
therefore cannot be flashed using an IRD container and is more or less “lost”.
Furthermore, the 1 Mbyte configuration partition is divided up in five single sub-
partitions, of which only the bottom four can be be written by the boot loader (note
from the translator: this not true for all receiver models).

Due to this fact, another 256 kbyte of the upper part of the flash memory cannot be
flashed by the boot loader on some receivers.

The Fortis IRD format Page 6


smogm GROUP LEViATHAN

3 Logical flash layout


The different partitions are not stored in memory by order of the ID number as one
would expect.
The next table showns the addresses as used by the early Fortis receiver models
with 32 Mbyte of flash memory. Other models may use layouts that are similar, but
different in some details.

ID Description Offset Length End


0 Bootloader 0x00000000 0x00300000 0x002FFFFF
6 Kernel 0x00300000 0x00300000 0x005FFFFF
- Application Low 0x00600000 0x00500000 0x00AFFFFF
1 Application High 0x00B00000 0x00500000 0x00FFFFFF
8 Root 0x01000000 0x00800000 0x017FFFFF
7 Device 0x01800000 0x00300000 0x01AFFFFF
2 Configuration0 0x01B00000 0x00040000 0x01B3FFFF
3 Configuration4 0x01B40000 0x00040000 0x01B7FFFF
4 Configuration8 0x01B80000 0x00020000 0x01B9FFFF
5 ConfigurationA 0x01BA0000 0x00020000 0x01BBFFFF
- ConfigurationC 0x01BC0000 0x00040000 0x01BFFFFF
9 User 0x01C00000 0x00400000 0x01FFFFFF

As can be seen, the partitions Application Low and ConfigurationC cannot be written
by using an IRD container.
These memory areas can only be reached at a later stage, when the Linux kernel
has taken over system control.

The Fortis IRD format Page 7


smogm GROUP LEViATHAN

4 Further checks by the bootloader


Before each normal start of the receiver, the Fortis boot loader will check a few
partitions for their integrity before the Linux kernel is started.

4.1 SquashFS check


The boot loader expects to find three (translator: original text says two, Device is
omitted) partitions to hold a valid zlib deflate compressed SquashFS 3.1 file system:
• Application High
• and thus also: the mirrored Application Low
• Root
• Device

Because SquashFS is a read only file system, in practice no changes in these


partitions will occur after flashing. For this reason Fortis calculates a CRC32
checksum for them, and attaches these four bytes at the end of the partition.
The boot loader will read the SquashFS superblock and calculates the absolute size
of the file system based on the information read. Then it reads the stored CRC32 at
the end of the file system, calculates the actual CRC32 of the file system and
compares the two checksums. When a mismatch is found, the boot process is
aborted and error 0x71 is shown if the error is in Root, 0x72 if it is in Device, or 0x01
(!) when it is in App High. The latter only occurs in receivers that do not backup App
(see below).
If the mentioned CRC32 checksum is not added when the IRD container is created,
the system will not boot.

4.2 The Application backup


Furthermore, the bootloader will check if the CRC32 checksum of the SquashFS
partition in Application Low and High are identical.
When a difference is found the boot loader will copy the SquashFS partition App
High to App Low and will then start the Linux kernel.
The boot loader tries to use the App High partition as backup, in case the App Low
partition which is normally used is damaged (why is this? SquashFS is read only and
the partition is mounted read only!)

4.3 Circumventing the SquashFS check


Because the boot loader expects to find a particular zlib deflate compressed
SquashFS 3.1 in the App Low, App High, Device and Root partitions, and does
accept anything else, one must use a trick to circumvent this check.
The boot loader checks the SquashFS file system using data read from its
superblock. This means that the bootloader will check the CRC32 at the end of the
file system, which is not necessarily the same as the end of the partition it resides in.
As an example: If a 1 Mbyte large SquashFS file system is stored in a 5 Mbyte large
partition, the bootloader will check the CRC32 located at (1 Mbyte + 1), and not the
value at 5 Mbyte - 4). In fact, the boot loader will not bother about the remainder of
the data in the partition.

The Fortis IRD format Page 8


smogm GROUP LEViATHAN

Herein lies the trick. Because zlib deflate compression when compared to LZMA is a
bit worse, it is not useful to compress ones own image with zlib deflate. A more
economical approach is to generate a minimal zlib deflated SquashFS partition and
to put this, including a correct CRC32, at the beginning of the partition, and then
append ones own compressed image in a file system of choice (SquashFS LZMA for
example, this would no longer require a CRC32 checksum).
The boot loader will then then only check the small fake partition, find it is correct,
and object no further.
(Note from translator: the previous is more or less an accurate translation of the
original text. However, enigma2 generates, changes and deletes files in the partition
it is running in, so SquashFS LZMA is out of the question, as it is read only. That
leaves JFFS2 or UBI. In practice JFFS2 is used. This file system will only mount as
read/write if it starts and ends on an erase block boundary.)

The boot loader will thus start the kernel because all is well regarding the things it is
concerned about. The kernel however must know where real partitions are located
(translator: this can be achieved by building the kernel with the actual “real” partition
layout, or by supplying the partition data on its command line).
At this point it is also necessary to know what the block size of the NAND flash chips
on the motherboard is. Because flash memory can only be read and written to in
blockwise fashion, the new actual partition must start at the beginning of a so-called
erase block (note from translator: the erase block size in most (if not all) Fortis
receivers is 128 kbyte (0x20000).)

If for instance the fake partition has a size of only 200 bytes and the erase block size
is 128 kbyte, the “real” file system cannot start from 200 bytes on, but at the earliest
at byte131072.

4.4 Circumventing the Application backup


As mentioned before, the boot loader will ignore the data following the fake
SquashFS file system, because the CRC32 location is determined by the file system
size and not the partition size.
This opens up the possiblity to store different data in the App Low and App high
partitions, thus making the full 10 Mbyte (translator: minus at least two erase blocks)
available. There is aproblem however: there no way to flash App Low, so this area
becomes usable only during and after the first start.
Because the boot loader only checks the two fake file systems it will only copy the
App High to App Low after flashing.
The kernel can then mount both partitions as separated file systems, format App Low
as JFFS2 and use it as such.
(Note from translator: later Fortis models no longer check the Application backup or
do not even have one.)

----------------------------

The Fortis IRD format Page 9