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