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