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