1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2013, The Chromium Authors
16 #include <u-boot/zlib.h>
19 #include <lzma/LzmaTypes.h>
20 #include <lzma/LzmaDec.h>
21 #include <lzma/LzmaTools.h>
23 #include <linux/lzo.h>
24 #include <test/compression.h>
25 #include <test/suites.h>
28 static const char plain[] =
29 "I am a highly compressable bit of text.\n"
30 "I am a highly compressable bit of text.\n"
31 "I am a highly compressable bit of text.\n"
32 "There are many like me, but this one is mine.\n"
33 "If I were any shorter, there wouldn't be much sense in\n"
34 "compressing me in the first place. At least with lzo, anyway,\n"
35 "which appears to behave poorly in the face of short text\n"
38 /* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
39 static const char bzip2_compressed[] =
40 "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
41 "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
42 "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
43 "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
44 "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
45 "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
46 "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
47 "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
48 "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
49 "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
50 "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
51 "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
52 "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
53 "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
54 "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
55 static const unsigned long bzip2_compressed_size = 240;
57 /* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
58 static const char lzma_compressed[] =
59 "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
60 "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
61 "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
62 "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
63 "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
64 "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
65 "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
66 "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
67 "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
68 "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
69 "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
70 "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
71 "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
72 "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
73 "\xfd\xf5\x50\x8d\xca";
74 static const unsigned long lzma_compressed_size = 229;
76 /* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
77 static const char lzo_compressed[] =
78 "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
79 "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
80 "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
81 "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
82 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
83 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
84 "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
85 "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
86 "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
87 "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
88 "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
89 "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
90 "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
91 "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
92 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
93 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
94 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
95 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
96 "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
97 "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
98 "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
99 static const unsigned long lzo_compressed_size = 334;
101 /* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
102 static const char lz4_compressed[] =
103 "\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61"
104 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
105 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
106 "\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20"
107 "\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65"
108 "\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69"
109 "\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00"
110 "\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00"
111 "\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75"
112 "\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69"
113 "\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73"
114 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
115 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77"
116 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
117 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
118 "\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
119 "\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
121 static const unsigned long lz4_compressed_size = 276;
124 #define TEST_BUFFER_SIZE 512
126 typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
127 void *, unsigned long, unsigned long *);
129 static int compress_using_gzip(struct unit_test_state *uts,
130 void *in, unsigned long in_size,
131 void *out, unsigned long out_max,
132 unsigned long *out_size)
135 unsigned long inout_size = out_max;
137 ret = gzip(out, &inout_size, in, in_size);
139 *out_size = inout_size;
144 static int uncompress_using_gzip(struct unit_test_state *uts,
145 void *in, unsigned long in_size,
146 void *out, unsigned long out_max,
147 unsigned long *out_size)
150 unsigned long inout_size = in_size;
152 ret = gunzip(out, out_max, in, &inout_size);
154 *out_size = inout_size;
159 static int compress_using_bzip2(struct unit_test_state *uts,
160 void *in, unsigned long in_size,
161 void *out, unsigned long out_max,
162 unsigned long *out_size)
164 /* There is no bzip2 compression in u-boot, so fake it. */
165 ut_asserteq(in_size, strlen(plain));
166 ut_asserteq(0, memcmp(plain, in, in_size));
168 if (bzip2_compressed_size > out_max)
171 memcpy(out, bzip2_compressed, bzip2_compressed_size);
173 *out_size = bzip2_compressed_size;
178 static int uncompress_using_bzip2(struct unit_test_state *uts,
179 void *in, unsigned long in_size,
180 void *out, unsigned long out_max,
181 unsigned long *out_size)
184 unsigned int inout_size = out_max;
186 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
187 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
189 *out_size = inout_size;
191 return (ret != BZ_OK);
194 static int compress_using_lzma(struct unit_test_state *uts,
195 void *in, unsigned long in_size,
196 void *out, unsigned long out_max,
197 unsigned long *out_size)
199 /* There is no lzma compression in u-boot, so fake it. */
200 ut_asserteq(in_size, strlen(plain));
201 ut_asserteq(0, memcmp(plain, in, in_size));
203 if (lzma_compressed_size > out_max)
206 memcpy(out, lzma_compressed, lzma_compressed_size);
208 *out_size = lzma_compressed_size;
213 static int uncompress_using_lzma(struct unit_test_state *uts,
214 void *in, unsigned long in_size,
215 void *out, unsigned long out_max,
216 unsigned long *out_size)
219 SizeT inout_size = out_max;
221 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
223 *out_size = inout_size;
225 return (ret != SZ_OK);
228 static int compress_using_lzo(struct unit_test_state *uts,
229 void *in, unsigned long in_size,
230 void *out, unsigned long out_max,
231 unsigned long *out_size)
233 /* There is no lzo compression in u-boot, so fake it. */
234 ut_asserteq(in_size, strlen(plain));
235 ut_asserteq(0, memcmp(plain, in, in_size));
237 if (lzo_compressed_size > out_max)
240 memcpy(out, lzo_compressed, lzo_compressed_size);
242 *out_size = lzo_compressed_size;
247 static int uncompress_using_lzo(struct unit_test_state *uts,
248 void *in, unsigned long in_size,
249 void *out, unsigned long out_max,
250 unsigned long *out_size)
253 size_t input_size = in_size;
254 size_t output_size = out_max;
256 ret = lzop_decompress(in, input_size, out, &output_size);
258 *out_size = output_size;
260 return (ret != LZO_E_OK);
263 static int compress_using_lz4(struct unit_test_state *uts,
264 void *in, unsigned long in_size,
265 void *out, unsigned long out_max,
266 unsigned long *out_size)
268 /* There is no lz4 compression in u-boot, so fake it. */
269 ut_asserteq(in_size, strlen(plain));
270 ut_asserteq(0, memcmp(plain, in, in_size));
272 if (lz4_compressed_size > out_max)
275 memcpy(out, lz4_compressed, lz4_compressed_size);
277 *out_size = lz4_compressed_size;
282 static int uncompress_using_lz4(struct unit_test_state *uts,
283 void *in, unsigned long in_size,
284 void *out, unsigned long out_max,
285 unsigned long *out_size)
288 size_t input_size = in_size;
289 size_t output_size = out_max;
291 ret = ulz4fn(in, input_size, out, &output_size);
293 *out_size = output_size;
298 #define errcheck(statement) if (!(statement)) { \
299 fprintf(stderr, "\tFailed: %s\n", #statement); \
306 ulong compressed_size;
307 ulong uncompressed_size;
309 void *compressed_buf;
310 void *uncompressed_buf;
314 static int run_test_internal(struct unit_test_state *uts, char *name,
315 mutate_func compress, mutate_func uncompress,
316 struct buf_state *buf)
320 /* Compress works as expected. */
321 printf("\torig_size:%lu\n", buf->orig_size);
322 memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
323 errcheck(compress(uts, buf->orig_buf, buf->orig_size,
324 buf->compressed_buf, buf->compressed_size,
325 &buf->compressed_size) == 0);
326 printf("\tcompressed_size:%lu\n", buf->compressed_size);
327 errcheck(buf->compressed_size > 0);
328 errcheck(buf->compressed_size < buf->orig_size);
329 errcheck(((char *)buf->compressed_buf)[buf->compressed_size - 1] !=
331 errcheck(((char *)buf->compressed_buf)[buf->compressed_size] == 'A');
333 /* Uncompresses with space remaining. */
334 errcheck(uncompress(uts, buf->compressed_buf, buf->compressed_size,
335 buf->uncompressed_buf, buf->uncompressed_size,
336 &buf->uncompressed_size) == 0);
337 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
338 errcheck(buf->uncompressed_size == buf->orig_size);
339 errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
340 buf->orig_size) == 0);
342 /* Uncompresses with exactly the right size output buffer. */
343 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
344 errcheck(uncompress(uts, buf->compressed_buf, buf->compressed_size,
345 buf->uncompressed_buf, buf->orig_size,
346 &buf->uncompressed_size) == 0);
347 errcheck(buf->uncompressed_size == buf->orig_size);
348 errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
349 buf->orig_size) == 0);
350 errcheck(((char *)buf->uncompressed_buf)[buf->orig_size] == 'A');
352 /* Make sure compression does not over-run. */
353 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
354 ret = compress(uts, buf->orig_buf, buf->orig_size,
355 buf->compare_buf, buf->compressed_size - 1,
357 errcheck(((char *)buf->compare_buf)[buf->compressed_size] == 'A');
359 printf("\tcompress does not overrun\n");
361 /* Make sure decompression does not over-run. */
362 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
363 ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
364 buf->compare_buf, buf->uncompressed_size - 1,
366 errcheck(((char *)buf->compare_buf)[buf->uncompressed_size - 1] == 'A');
368 printf("\tuncompress does not overrun\n");
370 /* Got here, everything is fine. */
377 static int run_test(struct unit_test_state *uts, char *name,
378 mutate_func compress, mutate_func uncompress)
380 struct buf_state sbuf, *buf = &sbuf;
383 printf(" testing %s ...\n", name);
385 buf->orig_buf = (void *)plain;
386 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
387 errcheck(buf->orig_size > 0);
389 buf->compressed_size = TEST_BUFFER_SIZE;
390 buf->uncompressed_size = TEST_BUFFER_SIZE;
391 buf->compressed_buf = malloc(buf->compressed_size);
392 errcheck(buf->compressed_buf);
393 buf->uncompressed_buf = malloc(buf->uncompressed_size);
394 errcheck(buf->uncompressed_buf);
395 buf->compare_buf = malloc(buf->uncompressed_size);
396 errcheck(buf->compare_buf);
398 ret = run_test_internal(uts, name, compress, uncompress, buf);
400 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
402 free(buf->compare_buf);
403 free(buf->uncompressed_buf);
404 free(buf->compressed_buf);
409 static int compression_test_gzip(struct unit_test_state *uts)
411 return run_test(uts, "gzip", compress_using_gzip,
412 uncompress_using_gzip);
414 COMPRESSION_TEST(compression_test_gzip, 0);
416 static int compression_test_bzip2(struct unit_test_state *uts)
418 return run_test(uts, "bzip2", compress_using_bzip2,
419 uncompress_using_bzip2);
421 COMPRESSION_TEST(compression_test_bzip2, 0);
423 static int compression_test_lzma(struct unit_test_state *uts)
425 return run_test(uts, "lzma", compress_using_lzma,
426 uncompress_using_lzma);
428 COMPRESSION_TEST(compression_test_lzma, 0);
430 static int compression_test_lzo(struct unit_test_state *uts)
432 return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
434 COMPRESSION_TEST(compression_test_lzo, 0);
436 static int compression_test_lz4(struct unit_test_state *uts)
438 return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
440 COMPRESSION_TEST(compression_test_lz4, 0);
442 static int compress_using_none(struct unit_test_state *uts,
443 void *in, unsigned long in_size,
444 void *out, unsigned long out_max,
445 unsigned long *out_size)
447 /* Here we just copy */
448 memcpy(out, in, in_size);
455 * run_bootm_test() - Run tests on the bootm decompression function
457 * @comp_type: Compression type to test
458 * @compress: Our function to compress data
459 * @return 0 if OK, non-zero on failure
461 static int run_bootm_test(struct unit_test_state *uts, int comp_type,
462 mutate_func compress)
464 ulong compress_size = 1024;
468 const ulong image_start = 0;
469 const ulong load_addr = 0x1000;
472 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
473 compress_buff = map_sysmem(image_start, 0);
474 unc_len = strlen(plain);
475 compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
477 err = image_decomp(comp_type, load_addr, image_start,
478 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
479 compress_buff, compress_size, unc_len,
482 err = image_decomp(comp_type, load_addr, image_start,
483 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
484 compress_buff, compress_size, unc_len - 1,
488 /* We can't detect corruption when not decompressing */
489 if (comp_type == IH_COMP_NONE)
491 memset(compress_buff + compress_size / 2, '\x49',
493 err = image_decomp(comp_type, load_addr, image_start,
494 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
495 compress_buff, compress_size, 0x10000,
502 static int compression_test_bootm_gzip(struct unit_test_state *uts)
504 return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
506 COMPRESSION_TEST(compression_test_bootm_gzip, 0);
508 static int compression_test_bootm_bzip2(struct unit_test_state *uts)
510 return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
512 COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
514 static int compression_test_bootm_lzma(struct unit_test_state *uts)
516 return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
518 COMPRESSION_TEST(compression_test_bootm_lzma, 0);
520 static int compression_test_bootm_lzo(struct unit_test_state *uts)
522 return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
524 COMPRESSION_TEST(compression_test_bootm_lzo, 0);
526 static int compression_test_bootm_lz4(struct unit_test_state *uts)
528 return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
530 COMPRESSION_TEST(compression_test_bootm_lz4, 0);
532 static int compression_test_bootm_none(struct unit_test_state *uts)
534 return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
536 COMPRESSION_TEST(compression_test_bootm_none, 0);
538 int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
541 struct unit_test *tests = ll_entry_start(struct unit_test,
543 const int n_ents = ll_entry_count(struct unit_test, compression_test);
545 return cmd_ut_category("compression", "compression_test_",
546 tests, n_ents, argc, argv);