If you like BoxMatrix then please contribute Supportdata-Probes, Firmware-Probes and/or Hardware-Probes (get in touch).

FIT-Image

From BoxMatrix

BoxMatrix >> Development >> FIT-Image @ BoxMatrix   -   IRC-Chat   -   Translate: de es fr it nl pl
News Selectors Models Accessories Components Environment Config Commands System Webif Software Develop Lexicon Community Project Gallery

Tarballs FW-Probes FW-History FW-News Supportdata Hardware SVN Trac Freetz-News Freetz-Timeline Freetz-Releases Freetz-Mirror OpenWRT Research

Introduction[edit]

Some new models do not contain kernel.image and filesystem.image in their firmware image any more but use a new fit-image instead.

FIT stands for Flattened Image Tree and is a container which can store multiple kernels, filesystems and device trees. FIT is also supported by the Uboot bootloader[1], but AVM uses an own derivative of the format, which so far has been a blackbox.

After analyzing the format I coded fitimg which permits to list, test, extract and recompose fit-image files.

Initally intended to just extract fit-images for the BoxMatrix Firmware-Scanner the Replace command opens the door to modifications of the Fritzbox 5530, 7530ax and Repeater 6000 models, if it works. Latest Recovery.exe scans showed there are likely more models to switch over to fit-images as you can see here: put-fitimage.

Download[edit]

Latest version of fitimg could be found here:

Requirements[edit]

  • Perl 5.6 or newer and the modules Getopt::Std (comes with Perl[2]) and String::CRC32
  • If you get an error Can't locate String/CRC32.pm ... install this module from CPAN (no need to be root, works for all systems):
cpan install String::CRC32

Depending on your system you can also install as root by one of these methods:

apt-get install libstring-crc32-perl
yum install perl-String-CRC32

Usage[edit]

Here a list of fitimg commands and options, including some usage examples:

List[edit]

The list command -l shows the memory region, size and name of each file in the fit-image.

Usage:

  fitimg -l <infile> [-f] [-q]
    List all binaries contained in fit-image <infile>.
    Option -f (freetz mode) uses filesystem/kernel.image etc instead of the stored names.
    Option -q could be used to silently test the image structure.

List in normal mode:

$ fitimg -l 6000.fit
41208000-41527046  3272774 qcaarmv8_HW253_kernel
41c30000-41c33cdd    15581 qcaarmv8_HW253_flat_dt_0
41c30000-41c33d0e    15630 qcaarmv8_HW253_flat_dt_2
43000000-44000000 16777216 qcaarmv8_HW253_squashFS_filesystem

$ fitimg -l 5530.fit
88000000-88122c69  1191017 prxB_HW0257_kernel
884e2000-884e2444     1092 prxB_HW0257_flat_dt_0
8b000000-8b19f361  1700705 prxB_HW0257_ramdisk
70000000-703216dc  3282652 prxI_HW257_kernel
70fe4000-70fe5eed     7917 prxI_HW257_flat_dt_0_aon
70fe4000-70fe5ecc     7884 prxI_HW257_flat_dt_0_pon
90000000-921d0c2d 35458093 prxI_HW257_ramdisk

$ fitimg -l 7530ax.fit
10800000-1082ef13   192275 brcma9TZ_HW256_kernel
10000000-10000257      599 brcma9TZ_HW256_flat_dt_0
c0008000-c0294542  2671938 brcma9_HW256_kernel
c07ab000-c07abee7     3815 brcma9_HW256_flat_dt_1
c07ab000-c07abee9     3817 brcma9_HW256_flat_dt_0
19c00000-1ba62000 31858688 brcma9_HW256_squashFS_filesystem

List in freetz mode:

$ fitimg -l 6000.fit -f
41208000-41527046  3272774 kernel.image
41c30000-41c33cdd    15581 flatdt_0.image
41c30000-41c33d0e    15630 flatdt_2.image
43000000-44000000 16777216 filesystem.image

$ fitimg -l 5530.fit -f
88000000-88122c69  1191017 kernel2.image
884e2000-884e2444     1092 flatdt2_0.image
8b000000-8b19f361  1700705 filesystem2.image
70000000-703216dc  3282652 kernel.image
70fe4000-70fe5eed     7917 flatdt_0_aon.image
70fe4000-70fe5ecc     7884 flatdt_0_pon.image
90000000-921d0c2d 35458093 filesystem.image

$ fitimg -l 7530ax.fit -f
10800000-1082ef13   192275 kernel2.image
10000000-10000257      599 flatdt2_0.image
c0008000-c0294542  2671938 kernel.image
c07ab000-c07abee7     3815 flatdt_1.image
c07ab000-c07abee9     3817 flatdt_0.image
19c00000-1ba62000 31858688 filesystem.image

Test[edit]

The test command -t lists and validates the stored and computed CRC32 checksums of each file in the fit-image.

Usage:

  fitimg -t <infile> [-f] [-q]
    Test the integrity of all binaries contained in fit-image <infile>. Performs CRC32 validation.
    Option -f (freetz mode) uses filesystem/kernel.image etc instead of the stored names.
    Option -q could be used to silently test the image structure and checksum integrity.

Test in normal mode:

$ fitimg -t 5530.fit
OK: b4761fdd b4761fdd  1191017 prxB_HW0257_kernel
OK: 3c53ca34 3c53ca34     1092 prxB_HW0257_flat_dt_0
OK: 0ef19ad8 0ef19ad8  1700705 prxB_HW0257_ramdisk
OK: aa110233 aa110233  3282652 prxI_HW257_kernel
OK: cf9e37b4 cf9e37b4     7917 prxI_HW257_flat_dt_0_aon
OK: b9298e1b b9298e1b     7884 prxI_HW257_flat_dt_0_pon
OK: 9b59e2d4 9b59e2d4 35458093 prxI_HW257_ramdisk
no errors in 7 files

Test in freetz mode:

$ fitimg -t 5530.fit -f
OK: b4761fdd b4761fdd  1191017 kernel2.image
OK: 3c53ca34 3c53ca34     1092 flatdt2_0.image
OK: 0ef19ad8 0ef19ad8  1700705 filesystem2.image
OK: aa110233 aa110233  3282652 kernel.image
OK: cf9e37b4 cf9e37b4     7917 flatdt_0_aon.image
OK: b9298e1b b9298e1b     7884 flatdt_0_pon.image
OK: 9b59e2d4 9b59e2d4 35458093 filesystem.image
no errors in 7 files

Extract[edit]

The extract command -x extracts files from the fit-image.

Usage:

  fitimg -x <infile> [-d <dir>] [-n] [-f] [-q]
    Extract all contents of fit-image <infile> or just <file> to current directory or <dir>.
    Option -n suppresses extracting device tree files.
    Option -f (freetz mode) uses filesystem/kernel.image etc instead of the stored names.
    Option -q suppresses listing which files were extracted.

Extract in normal mode:

$ fitimg -x 5530.fit -d temp 
OK: b4761fdd b4761fdd  1191017 prxB_HW0257_kernel
OK: 3c53ca34 3c53ca34     1092 prxB_HW0257_flat_dt_0
OK: 0ef19ad8 0ef19ad8  1700705 prxB_HW0257_ramdisk
OK: aa110233 aa110233  3282652 prxI_HW257_kernel
OK: cf9e37b4 cf9e37b4     7917 prxI_HW257_flat_dt_0_aon
OK: b9298e1b b9298e1b     7884 prxI_HW257_flat_dt_0_pon
OK: 9b59e2d4 9b59e2d4 35458093 prxI_HW257_ramdisk
extracted 7 files

Extract in freetz mode:

$ fitimg -x 5530.fit -d temp -f
OK: b4761fdd b4761fdd  1191017 kernel2.image
OK: 3c53ca34 3c53ca34     1092 flatdt2_0.image
OK: 0ef19ad8 0ef19ad8  1700705 filesystem2.image
OK: aa110233 aa110233  3282652 kernel.image
OK: cf9e37b4 cf9e37b4     7917 flatdt_0_aon.image
OK: b9298e1b b9298e1b     7884 flatdt_0_pon.image
OK: 9b59e2d4 9b59e2d4 35458093 filesystem.image
extracted 7 files

Extract in freetz mode, no device tree files:

$ fitimg -x 5530.fit -d temp -n -f
OK: b4761fdd b4761fdd  1191017 kernel2.image
OK: 0ef19ad8 0ef19ad8  1700705 filesystem2.image
OK: aa110233 aa110233  3282652 kernel.image
OK: 9b59e2d4 9b59e2d4 35458093 filesystem.image
extracted 4 files

Replace[edit]

The replace command -r creates a new image from the fit-image, replacing files in it.

Usage:

  fitimg -r <infile> -o <outfile> [-d <dir>] [-f] [-p <num>] [-q]
    Replace all contens of fit-image <infile> which exist in current directory or <dir> and write it to <outfile>.
    Files which do not exist in current directory or <dir> will not be replaced.
    Option -f (freetz mode) uses filesystem/kernel.image etc instead of the stored names.
    This is just an abstraction, the fit-image always stores the original names.
    Option -p ovverrides the default padding size of 64 (0 - 1024) in kB  (fitimg 0.5+)
    Option -q suppresses listing which files were replaced.

Replacing with the original files extracted above:
Note that starting with fitimg 0.5 you need to pass -p 0 for the md5 test.

$ fitimg -r 5530.fit -o temp/5530.fit -d temp -f
Replacing:  1191017-> 1191017 kernel2.image
Replacing:     1092->    1092 flatdt2_0.image
Replacing:  1700705-> 1700705 filesystem2.image
Replacing:  3282652-> 3282652 kernel.image
Replacing:     7917->    7917 flatdt_0_aon.image
Replacing:     7884->    7884 flatdt_0_pon.image
Replacing: 35458093->35458093 filesystem.image
replaced 7 files

$ md5sum 5530.fit temp/5530.fit
91952d629306e88791399a868c4491d9  5530.fit
91952d629306e88791399a868c4491d9  temp/5530.fit

Replacing with a modified filesystem.image:
Note that starting with fitimg 0.5 you need to pass -p 0 for the md5 test.

$ dd if=/dev/zero of=temp/filesystem.image bs=1024 count=16
16+0 records in
16+0 records out
16384 bytes (16 kB) copied, 0.0249391 s, 657 kB/s

$ fitimg -r 5530.fit -o temp/5530.fit -d temp -f
Replacing:  1191017-> 1191017 kernel2.image
Replacing:     1092->    1092 flatdt2_0.image
Replacing:  1700705-> 1700705 filesystem2.image
Replacing:  3282652-> 3282652 kernel.image
Replacing:     7917->    7917 flatdt_0_aon.image
Replacing:     7884->    7884 flatdt_0_pon.image
Replacing: 35458093->   16384 filesystem.image
replaced 7 files

$ md5sum 5530.fit temp/5530.fit
91952d629306e88791399a868c4491d9  5530.fit
4dfbe2a3f91037e7fed4832a93ef814c  temp/5530.fit

$ fitimg -l temp/5530.fit -f
88000000-88122c69  1191017 kernel2.image
884e2000-884e2444     1092 flatdt2_0.image
8b000000-8b19f361  1700705 filesystem2.image
70000000-703216dc  3282652 kernel.image
70fe4000-70fe5eed     7917 flatdt_0_aon.image
70fe4000-70fe5ecc     7884 flatdt_0_pon.image
90000000-90004000    16384 filesystem.image

$ fitimg -t temp/5530.fit -f
OK: b4761fdd b4761fdd  1191017 kernel2.image
OK: 3c53ca34 3c53ca34     1092 flatdt2_0.image
OK: 0ef19ad8 0ef19ad8  1700705 filesystem2.image
OK: aa110233 aa110233  3282652 kernel.image
OK: cf9e37b4 cf9e37b4     7917 flatdt_0_aon.image
OK: b9298e1b b9298e1b     7884 flatdt_0_pon.image
OK: ab54d286 ab54d286    16384 filesystem.image
no errors in 7 files

Copy[edit]

The copy command -c creates a new unaltered image from the fit-image and tests it. (fitimg 0.2+)
This is mainly useful to extract and validate a fit-image from a Recovery.exe or firmware.image, or to add padding.

Usage:

  fitimg -c <infile> -o <outfile> [-f] [-p <num>] [-q]
    Copy an unaltered fit-image from <infile> to <outfile> while testing its integrity.
    This is mainly useful to extract and validate a fit-image from a recovery.exe or firmware.image.
    Option -f (freetz mode) lists filesystem/kernel.image etc instead of the stored names.
    This is just an abstraction, the fit-image always stores the original names.
    Option -p ovverrides the default padding size of 64 (0 - 1024) in kB  (fitimg 0.5+)
    Option -q suppresses listing which files were copied and tested.

Copy and test a fit-image file:
Note that starting with fitimg 0.5 you need to pass -p 0 for the md5 test.

$ fitimg -c 7530ax.fit -o temp/7530ax.fit -f
OK: f653ffe8 f653ffe8   192275 kernel2.image
OK: 2040d9dd 2040d9dd      599 flatdt2_0.image
OK: 34ac9b5e 34ac9b5e  2671938 kernel.image
OK: 5edb6c64 5edb6c64     3815 flatdt_1.image
OK: a7ded150 a7ded150     3817 flatdt_0.image
OK: 29c318fc 29c318fc 31858688 filesystem.image
no errors copying fit image containing 6 files

$ md5sum 7530ax.fit temp/7530ax.fit
e41eafa4dc0c4ee6e46f5313dfce737f  7530ax.fit
e41eafa4dc0c4ee6e46f5313dfce737f  temp/7530ax.fit

Copy and test a fit-image from a firmware.image file:
Note that starting with fitimg 0.5 you need to pass -p 0 for the md5 test.

$ fitimg -c 7530ax.image -o temp/7530ax.fit -f
OK: f653ffe8 f653ffe8   192275 kernel2.image
OK: 2040d9dd 2040d9dd      599 flatdt2_0.image
OK: 34ac9b5e 34ac9b5e  2671938 kernel.image
OK: 5edb6c64 5edb6c64     3815 flatdt_1.image
OK: a7ded150 a7ded150     3817 flatdt_0.image
OK: 29c318fc 29c318fc 31858688 filesystem.image
no errors copying fit image containing 6 files

$ md5sum 7530ax.fit temp/7530ax.fit
e41eafa4dc0c4ee6e46f5313dfce737f  7530ax.fit
e41eafa4dc0c4ee6e46f5313dfce737f  temp/7530ax.fit

Copy and test a fit-image from a recovery.exe file:
Note that starting with fitimg 0.5 you need to pass -p 0 for the md5 test.

$ fitimg -c 7530ax.exe -o temp/7530ax.fit -f
OK: f653ffe8 f653ffe8   192275 kernel2.image
OK: 2040d9dd 2040d9dd      599 flatdt2_0.image
OK: 34ac9b5e 34ac9b5e  2671938 kernel.image
OK: 5edb6c64 5edb6c64     3815 flatdt_1.image
OK: a7ded150 a7ded150     3817 flatdt_0.image
OK: 29c318fc 29c318fc 31858688 filesystem.image
no errors copying fit image containing 6 files

$ md5sum 7530ax.fit temp/7530ax.fit
e41eafa4dc0c4ee6e46f5313dfce737f  7530ax.fit
e41eafa4dc0c4ee6e46f5313dfce737f  temp/7530ax.fit

Show[edit]

The show command -s shows the hunk structure of a fit-image, including hex offsets in the file. (fitimg 0.2+)
Hunks are given names as far as they are known, otherwise 'todo'. So far all hunknames of the 7530ax, 5530 and 6000 are known.
This command is useful to read metatada of all stored files and to understand the fit-format to improve this program.

Usage:

  fitimg -s <infile> [-h] [-q] (fitimg 0.2+)
    Show the complete hunk structure of the fit-image <infile>.
    Option -h adds a hexdump of all hunks, binaries clipped to 64 bytes
    Option -q could be used to silently test the image structure

Hunk structure of a 7530ax fit-image:

$ fitimg -s 7530ax.fit

00000080  hunk 1 [8] - string = ''
00000088  hunk 3 #0 [14] - info = 'FIT for HW256'
000000a4  hunk 3 #12 [4] - timestamp = 0x5fa13e4a
000000b4  hunk 3 #22 [4] - avm,gu-version = 0x0001451a

000000c4  hunk 1 [12] - string = 'images'

000000d0  hunk 1 [28] - string = 'brcma9TZ_HW256_kernel'
000000ec  hunk 3 #0 [26] - info = 'Kernel for brcma9TZ_HW256'
00000114  hunk 3 #37 [1] - avm,variants = 0x0badc0de
00000124  hunk 3 #50 [4] - #address-cells = 0x00000001
00000134  hunk 3 #65 [192275] - data = <binary blob>
0002f054  hunk 3 #70 [7] - type = 'kernel'
0002f068  hunk 3 #75 [4] - arch = 'arm'
0002f078  hunk 3 #80 [6] - os = 'linux'
0002f08c  hunk 3 #83 [5] - compression = 'lzma'
0002f0a0  hunk 3 #95 [4] - loadaddr = 0x10800000
0002f0b0  hunk 3 #100 [4] - entryaddr = 0x10800000
0002f0c0  hunk 1 [12] - string = 'hash_0'
0002f0cc  hunk 3 #106 [6] - hashalgo = 'crc32'
0002f0e0  hunk 3 #111 [4] - hashvalue = 0xf653ffe8

0002f0f0  hunk 2 [40] - string = 'brcma9TZ_HW256_flat_dt_0'
0002f118  hunk 3 #0 [33] - info = 'Device Tree for brcma9TZ_HW256_0'
0002f148  hunk 3 #50 [4] - #address-cells = 0x00000001
0002f158  hunk 3 #65 [599] - data = <binary blob>
0002f3bc  hunk 3 #70 [8] - type = 'flat_dt'
0002f3d0  hunk 3 #75 [4] - arch = 'arm'
0002f3e0  hunk 3 #83 [5] - compression = 'lzma'
0002f3f4  hunk 3 #95 [4] - loadaddr = 0x10000000
0002f404  hunk 3 #117 [1] - avm,kernel-args = ''
0002f414  hunk 1 [12] - string = 'hash_0'
0002f420  hunk 3 #106 [6] - hashalgo = 'crc32'
0002f434  hunk 3 #111 [4] - hashvalue = 0x2040d9dd

0002f444  hunk 2 [32] - string = 'brcma9_HW256_kernel'
0002f464  hunk 3 #0 [24] - info = 'Kernel for brcma9_HW256'
0002f488  hunk 3 #37 [1] - avm,variants = 0x0badc0de
0002f498  hunk 3 #50 [4] - #address-cells = 0x00000001
0002f4a8  hunk 3 #65 [2671938] - data = <binary blob>
002bb9f8  hunk 3 #70 [7] - type = 'kernel'
002bba0c  hunk 3 #75 [4] - arch = 'arm'
002bba1c  hunk 3 #80 [6] - os = 'linux'
002bba30  hunk 3 #83 [5] - compression = 'lzma'
002bba44  hunk 3 #95 [4] - loadaddr = 0xc0008000
002bba54  hunk 3 #100 [4] - entryaddr = 0xc0008000
002bba64  hunk 1 [12] - string = 'hash_0'
002bba70  hunk 3 #106 [6] - hashalgo = 'crc32'
002bba84  hunk 3 #111 [4] - hashvalue = 0x34ac9b5e

002bba94  hunk 2 [24] - string = 'avm,kallsyms'
002bbaac  hunk 3 #133 [3] - avm,endianess = 'LE'
002bbabc  hunk 3 #147 [4] - avm,kernel_text_start = 0xc0008000
002bbacc  hunk 3 #169 [4] - avm,names = 0xc0520920
002bbadc  hunk 3 #179 [4] - avm,token_table = 0xc058c9c0
002bbaec  hunk 3 #195 [4] - avm,token_index = 0xc058cd40
002bbafc  hunk 3 #211 [4] - avm,num_syms = 0xc0520910
002bbb0c  hunk 3 #224 [4] - avm,addresses = 0xc04fb9d0
002bbb1c  hunk 3 #238 [0] - avm,relative_base = 0x0badc0de
002bbb28  hunk 3 #256 [0] - avm,offsets = 0x0badc0de

002bbb34  hunk 2 [36] - string = 'brcma9_HW256_flat_dt_1'
002bbb58  hunk 3 #0 [31] - info = 'Device Tree for brcma9_HW256_1'
002bbb84  hunk 3 #50 [4] - #address-cells = 0x00000001
002bbb94  hunk 3 #65 [3815] - data = <binary blob>
002bca88  hunk 3 #70 [8] - type = 'flat_dt'
002bca9c  hunk 3 #75 [4] - arch = 'arm'
002bcaac  hunk 3 #83 [5] - compression = 'lzma'
002bcac0  hunk 3 #95 [4] - loadaddr = 0xc07ab000
002bcad0  hunk 1 [12] - string = 'hash_0'
002bcadc  hunk 3 #106 [6] - hashalgo = 'crc32'
002bcaf0  hunk 3 #111 [4] - hashvalue = 0x5edb6c64

002bcb00  hunk 2 [36] - string = 'brcma9_HW256_flat_dt_0'
002bcb24  hunk 3 #0 [31] - info = 'Device Tree for brcma9_HW256_0'
002bcb50  hunk 3 #50 [4] - #address-cells = 0x00000001
002bcb60  hunk 3 #65 [3817] - data = <binary blob>
002bda58  hunk 3 #70 [8] - type = 'flat_dt'
002bda6c  hunk 3 #75 [4] - arch = 'arm'
002bda7c  hunk 3 #83 [5] - compression = 'lzma'
002bda90  hunk 3 #95 [4] - loadaddr = 0xc07ab000
002bdaa0  hunk 1 [12] - string = 'hash_0'
002bdaac  hunk 3 #106 [6] - hashalgo = 'crc32'
002bdac0  hunk 3 #111 [4] - hashvalue = 0xa7ded150

002bdad0  hunk 2 [48] - string = 'brcma9_HW256_squashFS_filesystem'
002bdb00  hunk 3 #0 [26] - info = 'squashFS for brcma9_HW256'
002bdb28  hunk 3 #50 [4] - #address-cells = 0x00000001
002bdb38  hunk 3 #268 [4] - avm,data-align = 0x00001000
002bdb48  hunk 3 #65 [31858688] - data = <binary blob>
0211fb54  hunk 3 #70 [11] - type = 'filesystem'
0211fb6c  hunk 3 #83 [5] - compression = 'none'
0211fb80  hunk 3 #95 [4] - loadaddr = 0x19c00000
0211fb90  hunk 3 #117 [97] - avm,kernel-args = 'mtdram=ram-filesystem,0x19c00000,0x1bb00000 mtdparts_ext=ram-filesystem:31858688@0x0(rootfs_ram)'
0211fc00  hunk 1 [12] - string = 'hash_0'
0211fc0c  hunk 3 #106 [6] - hashalgo = 'crc32'
0211fc20  hunk 3 #111 [4] - hashvalue = 0x29c318fc

0211fc30  hunk 2 [32] - string = 'configurations'

0211fc50  hunk 1 [28] - string = 'brcma9TZ_HW256_config_0'
0211fc6c  hunk 3 #283 [22] - kernel = 'brcma9TZ_HW256_kernel'
0211fc90  hunk 3 #290 [25] - flatdt = 'brcma9TZ_HW256_flat_dt_0'

0211fcb8  hunk 2 [32] - string = 'brcma9_HW256_config_1'
0211fcd8  hunk 3 #283 [20] - kernel = 'brcma9_HW256_kernel'
0211fcf8  hunk 3 #290 [23] - flatdt = 'brcma9_HW256_flat_dt_1'
0211fd1c  hunk 3 #294 [33] - squashfs = 'brcma9_HW256_squashFS_filesystem'

0211fd4c  hunk 2 [32] - string = 'brcma9_HW256_config_0'
0211fd6c  hunk 3 #283 [20] - kernel = 'brcma9_HW256_kernel'
0211fd8c  hunk 3 #290 [23] - flatdt = 'brcma9_HW256_flat_dt_0'
0211fdb0  hunk 3 #294 [33] - squashfs = 'brcma9_HW256_squashFS_filesystem'

0211fde0  hunk 2 [28] - string = 'description'

0211fdfc  hunk -> [10] - array[] = 'timestamp'
0211fe06  hunk -> [15] - array[] = 'avm,gu-version'
0211fe15  hunk -> [13] - array[] = 'avm,variants'
0211fe22  hunk -> [15] - array[] = '#address-cells'
0211fe31  hunk -> [5] - array[] = 'data'
0211fe36  hunk -> [5] - array[] = 'type'
0211fe3b  hunk -> [5] - array[] = 'arch'
0211fe40  hunk -> [3] - array[] = 'os'
0211fe43  hunk -> [12] - array[] = 'compression'
0211fe4f  hunk -> [5] - array[] = 'load'
0211fe54  hunk -> [6] - array[] = 'entry'
0211fe5a  hunk -> [5] - array[] = 'algo'
0211fe5f  hunk -> [6] - array[] = 'value'
0211fe65  hunk -> [16] - array[] = 'avm,kernel-args'
0211fe75  hunk -> [14] - array[] = 'avm,endianess'
0211fe83  hunk -> [22] - array[] = 'avm,kernel_text_start'
0211fe99  hunk -> [10] - array[] = 'avm,names'
0211fea3  hunk -> [16] - array[] = 'avm,token_table'
0211feb3  hunk -> [16] - array[] = 'avm,token_index'
0211fec3  hunk -> [13] - array[] = 'avm,num_syms'
0211fed0  hunk -> [14] - array[] = 'avm,addresses'
0211fede  hunk -> [18] - array[] = 'avm,relative_base'
0211fef0  hunk -> [12] - array[] = 'avm,offsets'
0211fefc  hunk -> [15] - array[] = 'avm,data-align'
0211ff0b  hunk -> [7] - array[] = 'kernel'
0211ff12  hunk -> [4] - array[] = 'fdt'
0211ff16  hunk -> [9] - array[] = 'squashFS'

0211ff1f  hunk 0 [8] - hunk end

Hexdump[edit]

The hexdump command -h is a variant of the show command with an extra column listing every single byte in hex. (fitimg 0.5+)
The hunk payloads like binary blobs are clipped to 128 bytes. This is enough to not clip embedded kernel-args strings.
This command is useful for deeper inspection of the fit-format, and to add support for new models and hunk types in future.

Usage:

  fitimg -h <infile> [-q]  (fitimg 0.5+)
    Hexdump and show the complete structure of the fit-image <infile>.
    Hunk payload like binaries is clipped to 128 bytes, enough bytes to not clip kernel-args.
    Option -q could be used to silently test the image structure

Hexdumps are long, that's why this is just an excerpt from the head and tail of a 7530ax fit-image:

00000080 00000001  hunk 1 [8] - string = ''
00000084 00000000
00000088 00000003  hunk 3 #0 [14] - info = 'FIT for HW256'
0000008c 0000000e
00000090 00000000
00000094 46495420
00000098 666f7220
0000009c 48573235
000000a0 36000000
000000a4 00000003  hunk 3 #12 [4] - timestamp = 0x5fa13e4a
000000a8 00000004
000000ac 0000000c
000000b0 5fa13e4a
000000b4 00000003  hunk 3 #22 [4] - avm,gu-version = 0x0001451a
000000b8 00000004
000000bc 00000016
000000c0 0001451a

000000c4 00000001  hunk 1 [12] - string = 'images'
000000c8 696d6167
000000cc 65730000

000000d0 00000001  hunk 1 [28] - string = 'brcma9TZ_HW256_kernel'
000000d4 6272636d
000000d8 6139545a
000000dc 5f485732
000000e0 35365f6b
000000e4 65726e65
000000e8 6c000000
000000ec 00000003  hunk 3 #0 [26] - info = 'Kernel for brcma9TZ_HW256'
000000f0 0000001a
000000f4 00000000
000000f8 4b65726e
000000fc 656c2066
00000100 6f722062
00000104 72636d61
00000108 39545a5f
0000010c 48573235
00000110 36000000
00000114 00000003  hunk 3 #37 [1] - avm,variants = ''
00000118 00000001
0000011c 00000025
00000120 00000000
00000124 00000003  hunk 3 #50 [4] - #address-cells = 0x00000001
00000128 00000004
0000012c 00000032
00000130 00000001
00000134 00000003  hunk 3 #65 [192275] - data = <binary blob>
00000138 0002ef13
0000013c 00000041
00000140 5d000080
00000144 00006004
00000148 00000000
0000014c 00000715
00000150 13090c7d
00000154 22b80deb
00000158 32f59b17
0000015c 970b6e9c
00000160 41b6cefe
00000164 5eede1d5
00000168 4cd1c573
0000016c b529b72c
00000170 7b0f1cf1
00000174 0db3faf1
00000178 3674a850
0000017c 789dd563
00000180 64727b96
00000184 e0ee0147
00000188 f295a336
0000018c 7a91be66
00000190 aa0e6a3f
00000194 05719fc6
00000198 e6f00fc5
0000019c 590ac4d2
000001a0 bf1f1ae3
000001a4 113caca4
000001a8 016dde3d
000001ac 6b5707fd
000001b0 51d7f99d
.... <snip> ....
0002f054 00000003  hunk 3 #70 [7] - type = 'kernel'
0002f058 00000007
0002f05c 00000046
0002f060 6b65726e
0002f064 656c0000
0002f068 00000003  hunk 3 #75 [4] - arch = 'arm'
0002f06c 00000004
0002f070 0000004b
0002f074 61726d00
0002f078 00000003  hunk 3 #80 [6] - os = 'linux'
0002f07c 00000006
0002f080 00000050
0002f084 6c696e75
0002f088 78000000
0002f08c 00000003  hunk 3 #83 [5] - compression = 'lzma'
0002f090 00000005
0002f094 00000053
0002f098 6c7a6d61
0002f09c 00000000
0002f0a0 00000003  hunk 3 #95 [4] - loadaddr = 0x10800000
0002f0a4 00000004
0002f0a8 0000005f
0002f0ac 10800000
0002f0b0 00000003  hunk 3 #100 [4] - entryaddr = 0x10800000
0002f0b4 00000004
0002f0b8 00000064
0002f0bc 10800000
0002f0c0 00000001  hunk 1 [12] - string = 'hash_0'
0002f0c4 68617368
0002f0c8 5f300000
0002f0cc 00000003  hunk 3 #106 [6] - hashalgo = 'crc32'
0002f0d0 00000006
0002f0d4 0000006a
0002f0d8 63726333
0002f0dc 32000000
0002f0e0 00000003  hunk 3 #111 [4] - hashvalue = 0xf653ffe8
0002f0e4 00000004
0002f0e8 0000006f
0002f0ec f653ffe8

Tail:

0211fde0 00000002  hunk 2 [28] - string = 'description'
0211fde4 00000002
0211fde8 00000002
0211fdec 00000009
0211fdf0 64657363
0211fdf4 72697074
0211fdf8 696f6e00
0211fdfc 74696d65  hunk -> [9] - array[] = 'timestamp'
0211fe00 7374616d
0211fe04 7000....
0211fe04 ....6176  hunk -> [14] - array[] = 'avm,gu-version'
0211fe08 6d2c6775
0211fe0c 2d766572
0211fe10 73696f6e
0211fe14 00......
0211fe14 ..61766d  hunk -> [12] - array[] = 'avm,variants'
0211fe18 2c766172
0211fe1c 69616e74
0211fe20 7300....
0211fe20 ....2361  hunk -> [14] - array[] = '#address-cells'
0211fe24 64647265
0211fe28 73732d63
0211fe2c 656c6c73
0211fe30 00......
0211fe30 ..646174  hunk -> [4] - array[] = 'data'
0211fe34 6100....
0211fe34 ....7479  hunk -> [4] - array[] = 'type'
0211fe38 706500..
0211fe38 ......61  hunk -> [4] - array[] = 'arch'
0211fe3c 72636800
0211fe40 6f7300..
0211fe40 ......63  hunk -> [11] - array[] = 'compression'
0211fe44 6f6d7072
0211fe48 65737369
0211fe4c 6f6e00..
0211fe4c ......6c  hunk -> [4] - array[] = 'load'
0211fe50 6f616400
0211fe54 656e7472  hunk -> [5] - array[] = 'entry'
0211fe58 7900....
0211fe58 ....616c  hunk -> [4] - array[] = 'algo'
0211fe5c 676f00..
0211fe5c ......76  hunk -> [5] - array[] = 'value'
0211fe60 616c7565
0211fe64 00......
0211fe64 ..61766d  hunk -> [15] - array[] = 'avm,kernel-args'
0211fe68 2c6b6572
0211fe6c 6e656c2d
0211fe70 61726773
0211fe74 00......
0211fe74 ..61766d  hunk -> [13] - array[] = 'avm,endianess'
0211fe78 2c656e64
0211fe7c 69616e65
0211fe80 737300..
0211fe80 ......61  hunk -> [21] - array[] = 'avm,kernel_text_start'
0211fe84 766d2c6b
0211fe88 65726e65
0211fe8c 6c5f7465
0211fe90 78745f73
0211fe94 74617274
0211fe98 00......
0211fe98 ..61766d  hunk -> [9] - array[] = 'avm,names'
0211fe9c 2c6e616d
0211fea0 657300..
0211fea0 ......61  hunk -> [15] - array[] = 'avm,token_table'
0211fea4 766d2c74
0211fea8 6f6b656e
0211feac 5f746162
0211feb0 6c6500..
0211feb0 ......61  hunk -> [15] - array[] = 'avm,token_index'
0211feb4 766d2c74
0211feb8 6f6b656e
0211febc 5f696e64
0211fec0 657800..
0211fec0 ......61  hunk -> [12] - array[] = 'avm,num_syms'
0211fec4 766d2c6e
0211fec8 756d5f73
0211fecc 796d7300
0211fed0 61766d2c  hunk -> [13] - array[] = 'avm,addresses'
0211fed4 61646472
0211fed8 65737365
0211fedc 7300....
0211fedc ....6176  hunk -> [17] - array[] = 'avm,relative_base'
0211fee0 6d2c7265
0211fee4 6c617469
0211fee8 76655f62
0211feec 61736500
0211fef0 61766d2c  hunk -> [11] - array[] = 'avm,offsets'
0211fef4 6f666673
0211fef8 65747300
0211fefc 61766d2c  hunk -> [14] - array[] = 'avm,data-align'
0211ff00 64617461
0211ff04 2d616c69
0211ff08 676e00..
0211ff08 ......6b  hunk -> [6] - array[] = 'kernel'
0211ff0c 65726e65
0211ff10 6c00....
0211ff10 ....6664  hunk -> [3] - array[] = 'fdt'
0211ff14 7400....
0211ff14 ....7371  hunk -> [8] - array[] = 'squashFS'
0211ff18 75617368
0211ff1c 465300..
0211ff1c ......00  hunk 0 [0] - hunk end
0211ff20 00000000
0211ff24 000000..

Help[edit]

The help command --help prints a short help text and terminates.

$ fitimg --help
fitimg version 0.5 - (C) 2021 Ralf Steines aka Hippie2000 - <metamonk@yahoo.com>
Handle and manipulate firmware images in AVM /var/tmp/fit-image format. GPLv2+.
Docs and latest version can be found at https://boxmatrix.info/wiki/FIT-Image

Usage:
  fitimg -l <infile> [-f] [-q]
    List all binaries contained in fit-image <infile>.
    Option -q could be used to silently test the image structure.

  fitimg -t <infile> [-f] [-q]
    Test the integrity of all binaries contained in fit-image <infile>. Performs CRC32 validation.
    Option -q could be used to silently test the image structure and checksum integrity.

  fitimg -x <infile> [-d <dir>] [-n] [-f] [-q]
    Extract all contents of fit-image <infile> or just <file> to current directory or <dir>.
    Option -n suppresses extracting device tree files.
    Option -q suppresses listing which files were extracted.

  fitimg -r <infile> -o <outfile> [-d <dir>] [-f] [-p <num>] [-q]
    Replace all contens of fit-image <infile> which exist in current directory or <dir> and write it to <outfile>.
    Files which do not exist in current directory or <dir> will not be replaced.
    Option -p ovverrides the default padding size of 64 (0 - 1024) in kB  (fitimg 0.5+)
    Option -q suppresses listing which files were replaced.

  fitimg -c <infile> -o <outfile> [-f] [-p <num>] [-q]  (fitimg 0.2+)
    Copy an unaltered fit-image from <infile> to <outfile> while testing its integrity.
    This is mainly useful to extract and validate a fit-image from a recovery.exe or firmware.image.
    Option -p ovverrides the default padding size of 64 (0 - 1024) in kB  (fitimg 0.5+)
    Option -q could be used to silently copy and test the image structure and checksum integrity.

  fitimg -s <infile> [-q]  (fitimg 0.2+)
    Show the complete hunk structure of the fit-image <infile>.
    Option -q could be used to silently test the image structure

  fitimg -h <infile> [-q]  (fitimg 0.5+)
    Hexdump and show the complete structure of the fit-image <infile>.
    Hunk payload like binaries is clipped to 128 bytes, enough bytes to not clip kernel-args.
    Option -q could be used to silently test the image structure

Options:
  <infile> can be a fit-image, a firmware.image or a recovery.exe.  (fitimg 0.2+)
  -f activates Freetz mode using filesystem[2].image and kernel[2].image etc instead of the stored names.

  -? (fitimg 0.2+) or --help print this help text and terminates.
  -v (fitimg 0.2+) or --version print this program's version and terminates.

Result:
	Returns 1 on error, otherwise 0.

Version[edit]

The version command --version prints the program version and terminates.

$ fitimg --version
fitimg version 0.2 - (C) 2021 Ralf Steines aka Hippie2000 - <metamonk@yahoo.com>
Handle and manipulate firmware images in AVM /var/tmp/fit-image format.
Latest version can be found at https://boxmatrix.info/wiki/FIT-Image

Feedback[edit]

For bugreports or feature requests please get in touch or use this forum thread (german or english language please):

History[edit]

fitimg-todo - future

- TODO: Support for hex filesystem length in embedded kernel-args for replace (-r) command
- TODO: Add a 4-char ASCII column to hexdump mode
- TODO: Add adaption of the 5530 prx_I kernel entryaddr on freetz replace kernel to (-r) command

fitimg-0.5 - released 2021-02-10

- Added: The fitimg release archive now contains a readme.txt with the output of fitimg --help.
- Added: The new hexdump command (-h) is a variant of the show command for deeper inspection of the fit-image.
- Added: Now outputs a warning if an embedded kernel-args string of a replaced (-r) blob couldn't be adapted.
- Added: The 64kB default padding can be overridden using the -p <num> switch (0-1024, in kB, -r and -c mode).
- Added: Now creates 64kB padded images in replace (-r) and copy (-c) mode, as required by push_firmware later.
- Fixed: Zero sized integer hunks are now listed '<empty>' in show (-s) mode, ie: 'avm,addresses' on a 5530.
- Fixed: 'avm,variants' hunk is no longer an integer but a string in show (-s) mode, ie: 'aon, pon' on a 5530.

fitimg-0.4 - released 2021-02-08

- Fixed: Bug which computed wrong padding of new blob in replace mode.
- Fixed: Bug which reported missing blob if last blob in image grew in replace mode.
- Fixed: Bug which reported numerous "Use of uninitialized value" messages in replace mode.

fitimg-0.3 - released 2021-02-05

- Fixed: The kernel args stored in 7530ax and 6000 image now reflect the size of the modified filesystem (-r).
- Checked: Does loadaddr and entrypoint need adaption in replace (-r) command? - no - see research below.

fitimg-0.2 - released 2021-01-13

- Added: The show command (-s) now knows all hunknames of the 7530ax, 5360 and 6000.
- Added: A new show command (-s) can show the hunk structure of a fit-image. Useful for development.
- Added: A new copy command (-c) can extract a fit-image from a fit-image, firmware.image or recovery.exe.
- Changed: All commands now work on fit-image, firmware.image and recovery.exe files for the <infile>.
- Fixed: A nasty bug calculated wrong offsets in Replace (-r) when the fit-image filesize changes.
- Fixed: Removed wrong info in docs and help text which showed a [<file>] filter for the -x command. 
- Fixed: Bug which reported "Use of uninitialized value" if called without arguments.
- Fixed: The release archive now contains a versioned subfolder (in favour of the prior bin folder).

fitimg-0.1 - released 2021-01-02

Initial release.

Research[edit]

7530ax[edit]

Partition layout in Bootloader-Environment:

firstfreeaddress	0x1CE00000
flashsize	nor_size=0MB sflash_size=0KB nand_size=128MB
linux_fs_start    1
memsize	0x40000000
...
mtd0    0x0,0x0
mtd1    0xB00000,0x3D00000 = 50MB = fit0/fit1
mtd2    0x100000,0x300000 = 2MB = urlader
mtd3    0x300000,0xB00000 = 8MB = nand-tffs
mtd4    0x3D00000,0x6F00000 = 50MB = fit1/fit0
mtd5    0x0,0x100000 = 1MB = nvram
mtd6    0x6F00000,0x7F00000  = 16MB = ubi

The 128MB NAND is splitted into 50+50MB fit + 2MB urlader + 8MB nand-tffs + 1MB nvram + 16MB ubi = 127MB. 1MB is lost/hidden for whatever purposes.

Partition layout in Linux-Partitions:

major minor  #blocks  name
   1        0       8192 ram0 = 8MB = ramdisk oder kernel?
  31        0      31112 mtdblock0 = 30,4MB = rootfs_ram (ram-filesystem, squashfs)
  31        1      51200 mtdblock1 = 50MB = fit0 (brcmnand, fit-image)
  31        2       2048 mtdblock2 = 2MB = urlader (brcmnand)
  31        3       8192 mtdblock3 = 8MB = nand-tffs (brcmnand, tffs3-nand)
  31        4      51200 mtdblock4 = 50MB = fit1 (brcmnand, fit-image)
  31        5       1024 mtdblock5 = 1MB = nvram (brcmnand)
  31        6      16384 mtdblock6  = 16MB = ubi (brcmnand, ubi)
  31        7       2108 mtdblock7 = 2,05MB = [ubi_intern] (ubifs)
  31        8      12772 mtdblock8  = 12,5MB = avm_userdata (ubifs)

Kernel-args in fit-image:

env: firstfreeaddress 0x1CE00000      =>   0x1CE00000 − 0x19c00000 = 0x3200000 = 50MB = max fit0/fit1 partition size

0211fb80  hunk 3 #95 [4] - loadaddr = 0x19c00000
0211fb90  hunk 3 #117 [97] - avm,kernel-args = 'mtdram=ram-filesystem,0x19c00000,0x1bb00000 mtdparts_ext=ram-filesystem:31858688@0x0(rootfs_ram)'

021229e4  hunk 3 #95 [4] - loadaddr = 0x19c00000
021229f4  hunk 3 #117 [97] - avm,kernel-args = 'mtdram=ram-filesystem,0x19c00000,0x1bb00000 mtdparts_ext=ram-filesystem:31870976@0x0(rootfs_ram)'

The difference between the loadaddr and hex start addr in kernel args to the firstfreeaddress in env is exactly the 50MB max filesysten size.
This means startaddr and loadaddr remain static, endaddr must change, padded to 0x100000 / 1MB boundaries. The decimal size at the end of kernel args must change too, unpadded.

Recovery upload:

env: memsize 0x20000000     =>   0x20000000 - 34733863 = 0x1DEE00D9
fit-image: 34733863 = 0x211FF27

SETENV memsize 0x1dee0000
SETENV kernel_args_tmp "avm_fwupdate mtdram1=0x1dee0000,0x20000000 mtdparts_ext=update-image.0:0x2120000@0x0(fit-image)"
TYPE I
MEDIA SDRAM
P@SW
STOR 0x1dee0000 0x20000000

Here the second hex number endaddr stays static, taking the memsize value from environment.
The first hex number is the original memsize minus the fit-image size, padded to 0x10000 / 64kB boundaries.
This value is also used to set the new memsize, to protect the 'allocated' portion of RAM.
The third hex number is the fit-image size, padded to 0x10000 / 64kB boundaries.
Since EVA could not know the real size of the fit-image the upload has to be padded to 0x10000 / 64kB boundaries too.

7530ax flashing method research is finished.

5530[edit]

Partition layout in Bootloader-Environment:

firstfreeaddress	0x6043F420
flashsize	nor_size=0MB sflash_size=0KB nand_size=128MB
linux_fs_start    0
memsize	0x40000000
...
mtd0	0x0,0x0
mtd1	0x980000,0x3B80000 = 50MB = fit0/fit1
mtd2	0x0,0x180000 = 1.5MB = urlader
mtd3	0x180000,0x980000 = 8MB = nand-tffs
mtd4	0x3B80000,0x6D80000 = 50MB = fit1/fit0
mtd5	0x6D80000,0x8000000 = 18.5MB = ubi

The 128MB NAND is splitted into 50+50MB fit + 1.5MB urlader + 8MB nand-tffs + 18.5MB ubi = 128MB.

Partition layout in Linux-Partitions:

There's no mtd device listing so we take the bootlog:

[    7.523648] Creating 5 MTD partitions on "nand.0":
[    7.528426] 0x000000980000-0x000003b80000 : "fit0"
[    7.535728] 0x000000000000-0x000000180000 : "urlader"
[    7.541332] 0x000000180000-0x000000980000 : "nand-tffs"
[    7.547264] 0x000003b80000-0x000006d80000 : "fit1"
[    7.552870] 0x000006d80000-0x000008000000 : "ubi"
...
[   12.074234] ubi0: attached mtd4 (name "ubi", size 18 MiB)
[   12.078226] ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
[   12.085046] ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
[   12.091811] ubi0: VID header offset: 2048 (aligned 2048), data offset: 4096
[   12.098755] ubi0: good PEBs: 148, bad PEBs: 0, corrupted PEBs: 0
[   12.104746] ubi0: user volume: 0, internal volumes: 1, max. volumes count: 128

Kernel-args in fit-image:

There are no kernel-args in 5530 fit.

Recovery upload:

Strings from the recovery:

SETENV memsize 0x%x
SETENV kernel_args_tmp mtdram%u=0x%x,0x%x   =>  filesystem + kernel image ram upload
avm_fwupdate   =>  %s for the following:
SETENV kernel_args_tmp "%smtdram1=0x%x,0x%x mtdparts_ext=update-image.0:0x%x@0x0(fit-image)"  =>  fit-image ram upload
  • TODO:There is no recovery dump yet

6000[edit]

Partition layout in Bootloader-Environment:

firstfreeaddress	0x50500000
flashsize nor_size=0MB sflash_size=0KB nand_size=0MB emmc_size=1888MB
linux_fs_start 0
memsize	0x40000000
...
mtd0	0x0,0x0
mtd1	0x3000000,0x8000000 = 80MB = fit0/1
mtd2	0x0,0x2000000 = 32MB = urlader - wtf
mtd3	0x2000000,0x3000000 = 16MB = nand-tffs
mtd4	0x8000000,0xD000000 = 80MB = fit1/0
mtd5	0xD000000,0x75FFBE00 = 1680MB (1679.98389MB) = not ubi!

The 1888MB NAND is splitted into 80+80MB fit + 32MB urlader + 16MB nand-tffs + 1680MB not ubi = 1888MB.
This layout looks pretty unusual, maybe it's from a developer box.

Partition layout in Linux-Partitions:

  • There's no partition info in supportdata, neither in bootlog nor does a mtd device listing exist. What a pity.

Kernel-args in fit-image:

env: firstfreeaddress 0x50500000      =>   0x50500000 - 0x43000000 = 0xD500000 = 213MB = hmmmm!?!

01326f3c  hunk 3 #95 [4] - loadaddr = 0x43000000
01326f4c  hunk 3 #267 [97] - avm,kernel-args = 'mtdram=ram-filesystem,0x43000000,0x44100000 mtdparts_ext=ram-filesystem:16777216@0x0(rootfs_ram)'

Recovery upload:

  • TODO: No hardware and recovery, so there is no recovery dump yet

References