1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2013, The Chromium Authors
17 #include <u-boot/zlib.h>
20 #include <lzma/LzmaTypes.h>
21 #include <lzma/LzmaDec.h>
22 #include <lzma/LzmaTools.h>
24 #include <linux/lzo.h>
25 #include <test/compression.h>
26 #include <test/suites.h>
29 static const char plain[] =
30 "I am a highly compressable bit of text.\n"
31 "I am a highly compressable bit of text.\n"
32 "I am a highly compressable bit of text.\n"
33 "There are many like me, but this one is mine.\n"
34 "If I were any shorter, there wouldn't be much sense in\n"
35 "compressing me in the first place. At least with lzo, anyway,\n"
36 "which appears to behave poorly in the face of short text\n"
39 /* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
40 static const char bzip2_compressed[] =
41 "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
42 "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
43 "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
44 "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
45 "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
46 "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
47 "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
48 "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
49 "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
50 "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
51 "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
52 "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
53 "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
54 "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
55 "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
56 static const unsigned long bzip2_compressed_size = 240;
58 /* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
59 static const char lzma_compressed[] =
60 "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
61 "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
62 "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
63 "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
64 "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
65 "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
66 "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
67 "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
68 "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
69 "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
70 "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
71 "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
72 "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
73 "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
74 "\xfd\xf5\x50\x8d\xca";
75 static const unsigned long lzma_compressed_size = 229;
77 /* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
78 static const char lzo_compressed[] =
79 "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
80 "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
81 "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
82 "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
83 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
84 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
85 "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
86 "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
87 "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
88 "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
89 "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
90 "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
91 "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
92 "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
93 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
94 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
95 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
96 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
97 "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
98 "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
99 "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
100 static const unsigned long lzo_compressed_size = 334;
102 /* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
103 static const char lz4_compressed[] =
104 "\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61"
105 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
106 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
107 "\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20"
108 "\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65"
109 "\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69"
110 "\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00"
111 "\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00"
112 "\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75"
113 "\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69"
114 "\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73"
115 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
116 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77"
117 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
118 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
119 "\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
120 "\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
122 static const unsigned long lz4_compressed_size = 276;
125 #define TEST_BUFFER_SIZE 512
127 typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
128 void *, unsigned long, unsigned long *);
130 static int compress_using_gzip(struct unit_test_state *uts,
131 void *in, unsigned long in_size,
132 void *out, unsigned long out_max,
133 unsigned long *out_size)
136 unsigned long inout_size = out_max;
138 ret = gzip(out, &inout_size, in, in_size);
140 *out_size = inout_size;
145 static int uncompress_using_gzip(struct unit_test_state *uts,
146 void *in, unsigned long in_size,
147 void *out, unsigned long out_max,
148 unsigned long *out_size)
151 unsigned long inout_size = in_size;
153 ret = gunzip(out, out_max, in, &inout_size);
155 *out_size = inout_size;
160 static int compress_using_bzip2(struct unit_test_state *uts,
161 void *in, unsigned long in_size,
162 void *out, unsigned long out_max,
163 unsigned long *out_size)
165 /* There is no bzip2 compression in u-boot, so fake it. */
166 ut_asserteq(in_size, strlen(plain));
167 ut_asserteq_mem(plain, in, in_size);
169 if (bzip2_compressed_size > out_max)
172 memcpy(out, bzip2_compressed, bzip2_compressed_size);
174 *out_size = bzip2_compressed_size;
179 static int uncompress_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)
185 unsigned int inout_size = out_max;
187 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
188 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
190 *out_size = inout_size;
192 return (ret != BZ_OK);
195 static int compress_using_lzma(struct unit_test_state *uts,
196 void *in, unsigned long in_size,
197 void *out, unsigned long out_max,
198 unsigned long *out_size)
200 /* There is no lzma compression in u-boot, so fake it. */
201 ut_asserteq(in_size, strlen(plain));
202 ut_asserteq_mem(plain, in, in_size);
204 if (lzma_compressed_size > out_max)
207 memcpy(out, lzma_compressed, lzma_compressed_size);
209 *out_size = lzma_compressed_size;
214 static int uncompress_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)
220 SizeT inout_size = out_max;
222 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
224 *out_size = inout_size;
226 return (ret != SZ_OK);
229 static int compress_using_lzo(struct unit_test_state *uts,
230 void *in, unsigned long in_size,
231 void *out, unsigned long out_max,
232 unsigned long *out_size)
234 /* There is no lzo compression in u-boot, so fake it. */
235 ut_asserteq(in_size, strlen(plain));
236 ut_asserteq_mem(plain, in, in_size);
238 if (lzo_compressed_size > out_max)
241 memcpy(out, lzo_compressed, lzo_compressed_size);
243 *out_size = lzo_compressed_size;
248 static int uncompress_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)
254 size_t input_size = in_size;
255 size_t output_size = out_max;
257 ret = lzop_decompress(in, input_size, out, &output_size);
259 *out_size = output_size;
261 return (ret != LZO_E_OK);
264 static int compress_using_lz4(struct unit_test_state *uts,
265 void *in, unsigned long in_size,
266 void *out, unsigned long out_max,
267 unsigned long *out_size)
269 /* There is no lz4 compression in u-boot, so fake it. */
270 ut_asserteq(in_size, strlen(plain));
271 ut_asserteq_mem(plain, in, in_size);
273 if (lz4_compressed_size > out_max)
276 memcpy(out, lz4_compressed, lz4_compressed_size);
278 *out_size = lz4_compressed_size;
283 static int uncompress_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)
289 size_t input_size = in_size;
290 size_t output_size = out_max;
292 ret = ulz4fn(in, input_size, out, &output_size);
294 *out_size = output_size;
299 #define errcheck(statement) if (!(statement)) { \
300 fprintf(stderr, "\tFailed: %s\n", #statement); \
307 ulong compressed_size;
308 ulong uncompressed_size;
310 void *compressed_buf;
311 void *uncompressed_buf;
315 static int run_test_internal(struct unit_test_state *uts, char *name,
316 mutate_func compress, mutate_func uncompress,
317 struct buf_state *buf)
321 /* Compress works as expected. */
322 printf("\torig_size:%lu\n", buf->orig_size);
323 memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
324 errcheck(compress(uts, buf->orig_buf, buf->orig_size,
325 buf->compressed_buf, buf->compressed_size,
326 &buf->compressed_size) == 0);
327 printf("\tcompressed_size:%lu\n", buf->compressed_size);
328 errcheck(buf->compressed_size > 0);
329 errcheck(buf->compressed_size < buf->orig_size);
330 errcheck(((char *)buf->compressed_buf)[buf->compressed_size - 1] !=
332 errcheck(((char *)buf->compressed_buf)[buf->compressed_size] == 'A');
334 /* Uncompresses with space remaining. */
335 errcheck(uncompress(uts, buf->compressed_buf, buf->compressed_size,
336 buf->uncompressed_buf, buf->uncompressed_size,
337 &buf->uncompressed_size) == 0);
338 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
339 errcheck(buf->uncompressed_size == buf->orig_size);
340 errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
341 buf->orig_size) == 0);
343 /* Uncompresses with exactly the right size output buffer. */
344 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
345 errcheck(uncompress(uts, buf->compressed_buf, buf->compressed_size,
346 buf->uncompressed_buf, buf->orig_size,
347 &buf->uncompressed_size) == 0);
348 errcheck(buf->uncompressed_size == buf->orig_size);
349 errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
350 buf->orig_size) == 0);
351 errcheck(((char *)buf->uncompressed_buf)[buf->orig_size] == 'A');
353 /* Make sure compression does not over-run. */
354 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
355 ret = compress(uts, buf->orig_buf, buf->orig_size,
356 buf->compare_buf, buf->compressed_size - 1,
358 errcheck(((char *)buf->compare_buf)[buf->compressed_size] == 'A');
360 printf("\tcompress does not overrun\n");
362 /* Make sure decompression does not over-run. */
363 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
364 ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
365 buf->compare_buf, buf->uncompressed_size - 1,
367 errcheck(((char *)buf->compare_buf)[buf->uncompressed_size - 1] == 'A');
369 printf("\tuncompress does not overrun\n");
371 /* Got here, everything is fine. */
378 static int run_test(struct unit_test_state *uts, char *name,
379 mutate_func compress, mutate_func uncompress)
381 struct buf_state sbuf, *buf = &sbuf;
384 printf(" testing %s ...\n", name);
386 buf->orig_buf = (void *)plain;
387 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
388 errcheck(buf->orig_size > 0);
390 buf->compressed_size = TEST_BUFFER_SIZE;
391 buf->uncompressed_size = TEST_BUFFER_SIZE;
392 buf->compressed_buf = malloc(buf->compressed_size);
393 errcheck(buf->compressed_buf);
394 buf->uncompressed_buf = malloc(buf->uncompressed_size);
395 errcheck(buf->uncompressed_buf);
396 buf->compare_buf = malloc(buf->uncompressed_size);
397 errcheck(buf->compare_buf);
399 ret = run_test_internal(uts, name, compress, uncompress, buf);
401 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
403 free(buf->compare_buf);
404 free(buf->uncompressed_buf);
405 free(buf->compressed_buf);
410 static int compression_test_gzip(struct unit_test_state *uts)
412 return run_test(uts, "gzip", compress_using_gzip,
413 uncompress_using_gzip);
415 COMPRESSION_TEST(compression_test_gzip, 0);
417 static int compression_test_bzip2(struct unit_test_state *uts)
419 return run_test(uts, "bzip2", compress_using_bzip2,
420 uncompress_using_bzip2);
422 COMPRESSION_TEST(compression_test_bzip2, 0);
424 static int compression_test_lzma(struct unit_test_state *uts)
426 return run_test(uts, "lzma", compress_using_lzma,
427 uncompress_using_lzma);
429 COMPRESSION_TEST(compression_test_lzma, 0);
431 static int compression_test_lzo(struct unit_test_state *uts)
433 return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
435 COMPRESSION_TEST(compression_test_lzo, 0);
437 static int compression_test_lz4(struct unit_test_state *uts)
439 return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
441 COMPRESSION_TEST(compression_test_lz4, 0);
443 static int compress_using_none(struct unit_test_state *uts,
444 void *in, unsigned long in_size,
445 void *out, unsigned long out_max,
446 unsigned long *out_size)
448 /* Here we just copy */
449 memcpy(out, in, in_size);
456 * run_bootm_test() - Run tests on the bootm decompression function
458 * @comp_type: Compression type to test
459 * @compress: Our function to compress data
460 * @return 0 if OK, non-zero on failure
462 static int run_bootm_test(struct unit_test_state *uts, int comp_type,
463 mutate_func compress)
465 ulong compress_size = 1024;
469 const ulong image_start = 0;
470 const ulong load_addr = 0x1000;
473 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
474 compress_buff = map_sysmem(image_start, 0);
475 unc_len = strlen(plain);
476 compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
478 err = image_decomp(comp_type, load_addr, image_start,
479 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
480 compress_buff, compress_size, unc_len,
483 err = image_decomp(comp_type, load_addr, image_start,
484 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
485 compress_buff, compress_size, unc_len - 1,
489 /* We can't detect corruption when not decompressing */
490 if (comp_type == IH_COMP_NONE)
492 memset(compress_buff + compress_size / 2, '\x49',
494 err = image_decomp(comp_type, load_addr, image_start,
495 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
496 compress_buff, compress_size, 0x10000,
503 static int compression_test_bootm_gzip(struct unit_test_state *uts)
505 return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
507 COMPRESSION_TEST(compression_test_bootm_gzip, 0);
509 static int compression_test_bootm_bzip2(struct unit_test_state *uts)
511 return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
513 COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
515 static int compression_test_bootm_lzma(struct unit_test_state *uts)
517 return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
519 COMPRESSION_TEST(compression_test_bootm_lzma, 0);
521 static int compression_test_bootm_lzo(struct unit_test_state *uts)
523 return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
525 COMPRESSION_TEST(compression_test_bootm_lzo, 0);
527 static int compression_test_bootm_lz4(struct unit_test_state *uts)
529 return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
531 COMPRESSION_TEST(compression_test_bootm_lz4, 0);
533 static int compression_test_bootm_none(struct unit_test_state *uts)
535 return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
537 COMPRESSION_TEST(compression_test_bootm_none, 0);
539 int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
542 struct unit_test *tests = ll_entry_start(struct unit_test,
544 const int n_ents = ll_entry_count(struct unit_test, compression_test);
546 return cmd_ut_category("compression", "compression_test_",
547 tests, n_ents, argc, argv);