scripts: sd_fusing: Update a patch version to 2
[platform/kernel/u-boot.git] / test / compression.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013, The Chromium Authors
4  */
5
6 #include <common.h>
7 #include <abuf.h>
8 #include <bootm.h>
9 #include <command.h>
10 #include <gzip.h>
11 #include <image.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <mapmem.h>
15 #include <asm/io.h>
16
17 #include <u-boot/lz4.h>
18 #include <u-boot/zlib.h>
19 #include <bzlib.h>
20
21 #include <lzma/LzmaTypes.h>
22 #include <lzma/LzmaDec.h>
23 #include <lzma/LzmaTools.h>
24
25 #include <linux/lzo.h>
26 #include <linux/zstd.h>
27 #include <test/compression.h>
28 #include <test/suites.h>
29 #include <test/ut.h>
30
31 static const char plain[] =
32         "I am a highly compressable bit of text.\n"
33         "I am a highly compressable bit of text.\n"
34         "I am a highly compressable bit of text.\n"
35         "There are many like me, but this one is mine.\n"
36         "If I were any shorter, there wouldn't be much sense in\n"
37         "compressing me in the first place. At least with lzo, anyway,\n"
38         "which appears to behave poorly in the face of short text\n"
39         "messages.\n";
40
41 /* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
42 static const char bzip2_compressed[] =
43         "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
44         "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
45         "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
46         "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
47         "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
48         "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
49         "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
50         "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
51         "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
52         "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
53         "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
54         "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
55         "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
56         "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
57         "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
58 static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1;
59
60 /* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
61 static const char lzma_compressed[] =
62         "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
63         "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
64         "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
65         "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
66         "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
67         "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
68         "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
69         "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
70         "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
71         "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
72         "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
73         "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
74         "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
75         "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
76         "\xfd\xf5\x50\x8d\xca";
77 static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1;
78
79 /* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
80 static const char lzo_compressed[] =
81         "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
82         "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
83         "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
84         "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
85         "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
86         "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
87         "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
88         "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
89         "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
90         "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
91         "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
92         "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
93         "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
94         "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
95         "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
96         "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
97         "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
98         "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
99         "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
100         "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
101         "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
102 static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1;
103
104 /* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
105 static const char lz4_compressed[] =
106         "\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61"
107         "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
108         "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
109         "\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20"
110         "\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65"
111         "\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69"
112         "\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00"
113         "\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00"
114         "\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75"
115         "\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69"
116         "\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73"
117         "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
118         "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77"
119         "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
120         "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
121         "\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
122         "\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
123         "\x9d\x12\x8c\x9d";
124 static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1;
125
126 /* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */
127 static const char zstd_compressed[] =
128         "\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17"
129         "\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78"
130         "\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4"
131         "\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67"
132         "\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f"
133         "\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6"
134         "\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2"
135         "\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd"
136         "\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3"
137         "\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21"
138         "\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55"
139         "\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95"
140         "\x01\xe4\xf4\x6e\xfa";
141 static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1;
142
143
144 #define TEST_BUFFER_SIZE        512
145
146 typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
147                            void *, unsigned long, unsigned long *);
148
149 static int compress_using_gzip(struct unit_test_state *uts,
150                                void *in, unsigned long in_size,
151                                void *out, unsigned long out_max,
152                                unsigned long *out_size)
153 {
154         int ret;
155         unsigned long inout_size = out_max;
156
157         ret = gzip(out, &inout_size, in, in_size);
158         if (out_size)
159                 *out_size = inout_size;
160
161         return ret;
162 }
163
164 static int uncompress_using_gzip(struct unit_test_state *uts,
165                                  void *in, unsigned long in_size,
166                                  void *out, unsigned long out_max,
167                                  unsigned long *out_size)
168 {
169         int ret;
170         unsigned long inout_size = in_size;
171
172         ret = gunzip(out, out_max, in, &inout_size);
173         if (out_size)
174                 *out_size = inout_size;
175
176         return ret;
177 }
178
179 static int compress_using_bzip2(struct unit_test_state *uts,
180                                 void *in, unsigned long in_size,
181                                 void *out, unsigned long out_max,
182                                 unsigned long *out_size)
183 {
184         /* There is no bzip2 compression in u-boot, so fake it. */
185         ut_asserteq(in_size, strlen(plain));
186         ut_asserteq_mem(plain, in, in_size);
187
188         if (bzip2_compressed_size > out_max)
189                 return -1;
190
191         memcpy(out, bzip2_compressed, bzip2_compressed_size);
192         if (out_size)
193                 *out_size = bzip2_compressed_size;
194
195         return 0;
196 }
197
198 static int uncompress_using_bzip2(struct unit_test_state *uts,
199                                   void *in, unsigned long in_size,
200                                   void *out, unsigned long out_max,
201                                   unsigned long *out_size)
202 {
203         int ret;
204         unsigned int inout_size = out_max;
205
206         ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
207                         CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
208         if (out_size)
209                 *out_size = inout_size;
210
211         return (ret != BZ_OK);
212 }
213
214 static int compress_using_lzma(struct unit_test_state *uts,
215                                void *in, unsigned long in_size,
216                                void *out, unsigned long out_max,
217                                unsigned long *out_size)
218 {
219         /* There is no lzma compression in u-boot, so fake it. */
220         ut_asserteq(in_size,  strlen(plain));
221         ut_asserteq_mem(plain, in, in_size);
222
223         if (lzma_compressed_size > out_max)
224                 return -1;
225
226         memcpy(out, lzma_compressed, lzma_compressed_size);
227         if (out_size)
228                 *out_size = lzma_compressed_size;
229
230         return 0;
231 }
232
233 static int uncompress_using_lzma(struct unit_test_state *uts,
234                                  void *in, unsigned long in_size,
235                                  void *out, unsigned long out_max,
236                                  unsigned long *out_size)
237 {
238         int ret;
239         SizeT inout_size = out_max;
240
241         ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
242         if (out_size)
243                 *out_size = inout_size;
244
245         return (ret != SZ_OK);
246 }
247
248 static int compress_using_lzo(struct unit_test_state *uts,
249                               void *in, unsigned long in_size,
250                               void *out, unsigned long out_max,
251                               unsigned long *out_size)
252 {
253         /* There is no lzo compression in u-boot, so fake it. */
254         ut_asserteq(in_size,  strlen(plain));
255         ut_asserteq_mem(plain, in, in_size);
256
257         if (lzo_compressed_size > out_max)
258                 return -1;
259
260         memcpy(out, lzo_compressed, lzo_compressed_size);
261         if (out_size)
262                 *out_size = lzo_compressed_size;
263
264         return 0;
265 }
266
267 static int uncompress_using_lzo(struct unit_test_state *uts,
268                                 void *in, unsigned long in_size,
269                                 void *out, unsigned long out_max,
270                                 unsigned long *out_size)
271 {
272         int ret;
273         size_t input_size = in_size;
274         size_t output_size = out_max;
275
276         ret = lzop_decompress(in, input_size, out, &output_size);
277         if (out_size)
278                 *out_size = output_size;
279
280         return (ret != LZO_E_OK);
281 }
282
283 static int compress_using_lz4(struct unit_test_state *uts,
284                               void *in, unsigned long in_size,
285                               void *out, unsigned long out_max,
286                               unsigned long *out_size)
287 {
288         /* There is no lz4 compression in u-boot, so fake it. */
289         ut_asserteq(in_size,  strlen(plain));
290         ut_asserteq_mem(plain, in, in_size);
291
292         if (lz4_compressed_size > out_max)
293                 return -1;
294
295         memcpy(out, lz4_compressed, lz4_compressed_size);
296         if (out_size)
297                 *out_size = lz4_compressed_size;
298
299         return 0;
300 }
301
302 static int uncompress_using_lz4(struct unit_test_state *uts,
303                                 void *in, unsigned long in_size,
304                                 void *out, unsigned long out_max,
305                                 unsigned long *out_size)
306 {
307         int ret;
308         size_t input_size = in_size;
309         size_t output_size = out_max;
310
311         ret = ulz4fn(in, input_size, out, &output_size);
312         if (out_size)
313                 *out_size = output_size;
314
315         return (ret != 0);
316 }
317
318 static int compress_using_zstd(struct unit_test_state *uts,
319                                void *in, unsigned long in_size,
320                                void *out, unsigned long out_max,
321                                unsigned long *out_size)
322 {
323         /* There is no zstd compression in u-boot, so fake it. */
324         ut_asserteq(in_size, strlen(plain));
325         ut_asserteq_mem(plain, in, in_size);
326
327         if (zstd_compressed_size > out_max)
328                 return -1;
329
330         memcpy(out, zstd_compressed, zstd_compressed_size);
331         if (out_size)
332                 *out_size = zstd_compressed_size;
333
334         return 0;
335 }
336
337 static int uncompress_using_zstd(struct unit_test_state *uts,
338                                  void *in, unsigned long in_size,
339                                  void *out, unsigned long out_max,
340                                  unsigned long *out_size)
341 {
342         struct abuf in_buf, out_buf;
343         int ret;
344
345         abuf_init_set(&in_buf, in, in_size);
346         abuf_init_set(&out_buf, out, out_max);
347
348         ret = zstd_decompress(&in_buf, &out_buf);
349         if (ret >= 0) {
350                 *out_size = ret;
351                 ret = 0;
352         }
353
354         return ret;
355 }
356
357 #define errcheck(statement) if (!(statement)) { \
358         fprintf(stderr, "\tFailed: %s\n", #statement); \
359         ret = 1; \
360         goto out; \
361 }
362
363 struct buf_state {
364         ulong orig_size;
365         ulong compressed_size;
366         ulong uncompressed_size;
367         void *orig_buf;
368         void *compressed_buf;
369         void *uncompressed_buf;
370         void *compare_buf;
371 };
372
373 static int run_test_internal(struct unit_test_state *uts, char *name,
374                              mutate_func compress, mutate_func uncompress,
375                              struct buf_state *buf)
376 {
377         int ret;
378
379         /* Compress works as expected. */
380         printf("\torig_size:%lu\n", buf->orig_size);
381         memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
382         ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
383                           buf->compressed_buf, buf->compressed_size,
384                           &buf->compressed_size));
385         printf("\tcompressed_size:%lu\n", buf->compressed_size);
386         ut_assert(buf->compressed_size > 0);
387         ut_assert(buf->compressed_size < buf->orig_size);
388         ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
389                         != 'A');
390         ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
391
392         /* Uncompresses with space remaining. */
393         ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
394                             buf->uncompressed_buf, buf->uncompressed_size,
395                             &buf->uncompressed_size));
396         printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
397         ut_asserteq(buf->uncompressed_size, buf->orig_size);
398         ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
399
400         /* Uncompresses with exactly the right size output buffer. */
401         memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
402         ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
403                             buf->uncompressed_buf, buf->orig_size,
404                             &buf->uncompressed_size));
405         ut_asserteq(buf->uncompressed_size, buf->orig_size);
406         ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
407         ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
408
409         /* Uncompresses with trailing garbage in input buffer. */
410         memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
411         ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
412                             buf->uncompressed_buf, buf->uncompressed_size,
413                             &buf->uncompressed_size));
414         ut_asserteq(buf->uncompressed_size, buf->orig_size);
415         ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
416
417         /* Make sure compression does not over-run. */
418         memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
419         ret = compress(uts, buf->orig_buf, buf->orig_size,
420                        buf->compare_buf, buf->compressed_size - 1,
421                        NULL);
422         ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
423         ut_assert(ret != 0);
424         printf("\tcompress does not overrun\n");
425
426         /* Make sure decompression does not over-run. */
427         memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
428         ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
429                          buf->compare_buf, buf->uncompressed_size - 1,
430                          NULL);
431         ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
432         ut_assert(ret != 0);
433         printf("\tuncompress does not overrun\n");
434
435         /* Got here, everything is fine. */
436         return 0;
437 }
438
439 static int run_test(struct unit_test_state *uts, char *name,
440                     mutate_func compress, mutate_func uncompress)
441 {
442         struct buf_state sbuf, *buf = &sbuf;
443         int ret;
444
445         printf(" testing %s ...\n", name);
446
447         buf->orig_buf = (void *)plain;
448         buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
449         errcheck(buf->orig_size > 0);
450
451         buf->compressed_size = TEST_BUFFER_SIZE;
452         buf->uncompressed_size = TEST_BUFFER_SIZE;
453         buf->compressed_buf = malloc(buf->compressed_size);
454         errcheck(buf->compressed_buf);
455         buf->uncompressed_buf = malloc(buf->uncompressed_size);
456         errcheck(buf->uncompressed_buf);
457         buf->compare_buf = malloc(buf->uncompressed_size);
458         errcheck(buf->compare_buf);
459
460         ret = run_test_internal(uts, name, compress, uncompress, buf);
461 out:
462         printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
463
464         free(buf->compare_buf);
465         free(buf->uncompressed_buf);
466         free(buf->compressed_buf);
467
468         return ret;
469 }
470
471 static int compression_test_gzip(struct unit_test_state *uts)
472 {
473         return run_test(uts, "gzip", compress_using_gzip,
474                         uncompress_using_gzip);
475 }
476 COMPRESSION_TEST(compression_test_gzip, 0);
477
478 static int compression_test_bzip2(struct unit_test_state *uts)
479 {
480         return run_test(uts, "bzip2", compress_using_bzip2,
481                         uncompress_using_bzip2);
482 }
483 COMPRESSION_TEST(compression_test_bzip2, 0);
484
485 static int compression_test_lzma(struct unit_test_state *uts)
486 {
487         return run_test(uts, "lzma", compress_using_lzma,
488                         uncompress_using_lzma);
489 }
490 COMPRESSION_TEST(compression_test_lzma, 0);
491
492 static int compression_test_lzo(struct unit_test_state *uts)
493 {
494         return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
495 }
496 COMPRESSION_TEST(compression_test_lzo, 0);
497
498 static int compression_test_lz4(struct unit_test_state *uts)
499 {
500         return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
501 }
502 COMPRESSION_TEST(compression_test_lz4, 0);
503
504 static int compression_test_zstd(struct unit_test_state *uts)
505 {
506         return run_test(uts, "zstd", compress_using_zstd,
507                         uncompress_using_zstd);
508 }
509 COMPRESSION_TEST(compression_test_zstd, 0);
510
511 static int compress_using_none(struct unit_test_state *uts,
512                                void *in, unsigned long in_size,
513                                void *out, unsigned long out_max,
514                                unsigned long *out_size)
515 {
516         /* Here we just copy */
517         memcpy(out, in, in_size);
518         *out_size = in_size;
519
520         return 0;
521 }
522
523 /**
524  * run_bootm_test() - Run tests on the bootm decompression function
525  *
526  * @comp_type:  Compression type to test
527  * @compress:   Our function to compress data
528  * Return: 0 if OK, non-zero on failure
529  */
530 static int run_bootm_test(struct unit_test_state *uts, int comp_type,
531                           mutate_func compress)
532 {
533         ulong compress_size = 1024;
534         void *compress_buff;
535         int unc_len;
536         int err = 0;
537         const ulong image_start = 0;
538         const ulong load_addr = 0x1000;
539         ulong load_end;
540
541         printf("Testing: %s\n", genimg_get_comp_name(comp_type));
542         compress_buff = map_sysmem(image_start, 0);
543         unc_len = strlen(plain);
544         compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
545                  &compress_size);
546         err = image_decomp(comp_type, load_addr, image_start,
547                            IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
548                            compress_buff, compress_size, unc_len,
549                            &load_end);
550         ut_assertok(err);
551         err = image_decomp(comp_type, load_addr, image_start,
552                            IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
553                            compress_buff, compress_size, unc_len - 1,
554                            &load_end);
555         ut_assert(err);
556
557         /* We can't detect corruption when not decompressing */
558         if (comp_type == IH_COMP_NONE)
559                 return 0;
560         memset(compress_buff + compress_size / 2, '\x49',
561                compress_size / 2);
562         err = image_decomp(comp_type, load_addr, image_start,
563                            IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
564                            compress_buff, compress_size, 0x10000,
565                            &load_end);
566         ut_assert(err);
567
568         return 0;
569 }
570
571 static int compression_test_bootm_gzip(struct unit_test_state *uts)
572 {
573         return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
574 }
575 COMPRESSION_TEST(compression_test_bootm_gzip, 0);
576
577 static int compression_test_bootm_bzip2(struct unit_test_state *uts)
578 {
579         return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
580 }
581 COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
582
583 static int compression_test_bootm_lzma(struct unit_test_state *uts)
584 {
585         return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
586 }
587 COMPRESSION_TEST(compression_test_bootm_lzma, 0);
588
589 static int compression_test_bootm_lzo(struct unit_test_state *uts)
590 {
591         return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
592 }
593 COMPRESSION_TEST(compression_test_bootm_lzo, 0);
594
595 static int compression_test_bootm_lz4(struct unit_test_state *uts)
596 {
597         return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
598 }
599 COMPRESSION_TEST(compression_test_bootm_lz4, 0);
600
601 static int compression_test_bootm_zstd(struct unit_test_state *uts)
602 {
603         return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
604 }
605 COMPRESSION_TEST(compression_test_bootm_zstd, 0);
606
607 static int compression_test_bootm_none(struct unit_test_state *uts)
608 {
609         return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
610 }
611 COMPRESSION_TEST(compression_test_bootm_none, 0);
612
613 int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
614                       char *const argv[])
615 {
616         struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
617         const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
618
619         return cmd_ut_category("compression", "compression_test_",
620                                tests, n_ents, argc, argv);
621 }