1# Compressed binary file internals
2
3This article describes the structure of the
4`zephyr.signed.bin` file when image
5compression is enabled. You do not need to know these details to use the
6image compression subsystem, but they can be beneficial if you want to
7use them for verification or custom integration purposes.
8
9For an example, see the following structure of the file:
10
11![LZMA header](./images/decomp.png)
12
13## [LZMA Header](#LZMA-Header)
14
15The Lempel-Ziv-Markov chain Algorithm (LZMA) header is crucial for files
16compressed using the LZMA method. It contains metadata essential for
17decompression. The `lzma2_header` encodes compression parameters using
18two bytes.
19
20### [Calculating compression parameters](#Calculating-compression-parameters)
21
22Compression parameters can be calculated, retrieved, or changed
23depending on your needs. For details, see the following sections.
24
25#### [Default values](#Default-values)
26
27Compression parameters have the following default values:
28
29-   `dict_size`: 131072
30-   `pb`: 2
31-   `lc`: 3
32-   `lp`: 1
33
34#### [Adjusting dictionary size](#Adjusting-dictionary-size)
35
36You can calculate the `dict_size` using the following method:
37
38``` {.c}
39unsigned int i = 0;
40
41for (i = 0; i < 40; i++) {
42    if (raw_dict_size <= (((uint32_t)2 | ((i) & 1)) << ((i) / 2 + 11))) {
43        break;
44    }
45}
46dict_size = (uint8_t)i;
47```
48
49With this method, `dict_size` can have one of the following values:
50
51 |Hex Value  |  Size      |
52 |-----------|------------|
53 |0x00       | 4096       |
54 |0x01       | 6144       |
55 |0x02       | 8192       |
56 |0x03       | 12288      |
57 |0x04       | 16384      |
58 |0x05       | 24576      |
59 |0x06       | 32768      |
60 |0x07       | 49152      |
61 |0x08       | 65536      |
62 |0x09       | 98304      |
63 |0x0a       | 131072     |
64 |0x0b       | 196608     |
65 |0x0c       | 262144     |
66 |0x0d       | 393216     |
67 |0x0e       | 524288     |
68 |0x0f       | 786432     |
69 |0x10       | 1048576    |
70 |0x11       | 1572864    |
71 |0x12       | 2097152    |
72 |0x13       | 3145728    |
73 |0x14       | 4194304    |
74 |0x15       | 6291456    |
75 |0x16       | 8388608    |
76 |0x17       | 12582912   |
77 |0x18       | 16777216   |
78 |0x19       | 25165824   |
79 |0x1a       | 33554432   |
80 |0x1b       | 50331648   |
81 |0x1c       | 67108864   |
82 |0x1d       | 100663296  |
83 |0x1e       | 134217728  |
84 |0x1f       | 201326592  |
85 |0x20       | 268435456  |
86 |0x21       | 402653184  |
87 |0x22       | 536870912  |
88 |0x23       | 805306368  |
89 |0x24       | 1073741824 |
90 |0x25       | 1610612736 |
91 |0x26       | 2147483648 |
92 |0x27       | 3221225472 |
93
94#### [Calculating literal context, literal pos, and pos bits](#Calculating-literal-context-literal-pos-and-pos-bits)
95
96The second byte of the `lzma2_header` carries the following parameters:
97
98-   `lc`, which specifies a number of literal context bits
99
100-   `lp`, which specifies a number of literal pos bits
101
102-   `pb`, which specifies a number of pos bits
103
104    These parameters are encoded with the following formula:
105
106    ``` {.c}
107    pb_lp_lc = (uint8_t)((pb * 5 + lp) * 9 + lc);
108    ```
109
110    To decode these values from the combined `pb_lp_lc` byte, run the
111    following code:
112
113    ``` {.c}
114    lc = pb_lp_lc % 9;
115    pb_lp_lc /= 9;
116    pb = pb_lp_lc / 5;
117    lp = pb_lp_lc % 5;
118    ```
119
120## [Extracting LZMA stream from image](#Extracting-LZMA-stream-from-image)
121
122To extract and decompress the LZMA stream from the image, follow these
123steps:
124
1251.  Determine the offset of the compressed stream by adding the
126    `lzma2_header` size and the value stored under
127    `image_header.ih_hdr_size`. For the size of the compressed stream,
128    see `image_header.ih_img_size`.
1292.  If the compressed stream is isolated and stored in a file named
130    `raw.lzma`, you can perform
131    decompression using the following commands:
132
133 -   Without an ARM thumb filter:
134
135     ``` {.bash}
136     unlzma --lzma2 --format=raw --suffix=.lzma raw.lzma
137     ```
138
139 -   With an ARM thumb filter:
140
141     ``` {.bash}
142     unlzma --armthumb --lzma2 --format=raw --suffix=.lzma raw.lzma
143     ```
144
145Once the command is executed you will see a newly created file named
146`raw`, which is identical to the
147image before compression.
148
149## [TLVs](#TLVs)
150
151The following Type-Length-Values (TLVs) are used in the context of
152decompressed images:
153
154-   `DECOMP_SIZE (0x70)`: Specifies the size of the decompressed image.
155-   `DECOMP_SHA (0x71)`: Contains the hash of the decompressed image.
156-   `DECOMP_SIGNATURE (0x72)`: Holds the signature of either the hash or
157    the entire image.
158
159These TLVs are placed in the protected TLV section, ensuring they are
160included in the hashing and signature calculations during the
161verification process. The process for choosing the type of cryptographic
162signature and hash algorithm used for securing the image is the same,
163regardless of whether the image has undergone compression.
164
165## [Sample](#Sample)
166
167For practical implementation, you can find a simple stand-alone
168verification program under the following path
169`bootloader/mcuboot/samples/compression_test/independent_cmp.c`
170
171This program demonstrates how to independently verify the integrity and
172authenticity of a decompressed image using the specified TLVs.
173