1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2013, The Chromium Authors
16 #include <u-boot/lz4.h>
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 = sizeof(bzip2_compressed) - 1;
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 = sizeof(lzma_compressed) - 1;
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 = sizeof(lzo_compressed) - 1;
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 = sizeof(lz4_compressed) - 1;
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 ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
325 buf->compressed_buf, buf->compressed_size,
326 &buf->compressed_size));
327 printf("\tcompressed_size:%lu\n", buf->compressed_size);
328 ut_assert(buf->compressed_size > 0);
329 ut_assert(buf->compressed_size < buf->orig_size);
330 ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
332 ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
334 /* Uncompresses with space remaining. */
335 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
336 buf->uncompressed_buf, buf->uncompressed_size,
337 &buf->uncompressed_size));
338 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
339 ut_asserteq(buf->uncompressed_size, buf->orig_size);
340 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
342 /* Uncompresses with exactly the right size output buffer. */
343 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
344 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
345 buf->uncompressed_buf, buf->orig_size,
346 &buf->uncompressed_size));
347 ut_asserteq(buf->uncompressed_size, buf->orig_size);
348 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
349 ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
351 /* Uncompresses with trailing garbage in input buffer. */
352 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
353 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
354 buf->uncompressed_buf, buf->uncompressed_size,
355 &buf->uncompressed_size));
356 ut_asserteq(buf->uncompressed_size, buf->orig_size);
357 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
359 /* Make sure compression does not over-run. */
360 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
361 ret = compress(uts, buf->orig_buf, buf->orig_size,
362 buf->compare_buf, buf->compressed_size - 1,
364 ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
366 printf("\tcompress does not overrun\n");
368 /* Make sure decompression does not over-run. */
369 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
370 ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
371 buf->compare_buf, buf->uncompressed_size - 1,
373 ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
375 printf("\tuncompress does not overrun\n");
377 /* Got here, everything is fine. */
381 static int run_test(struct unit_test_state *uts, char *name,
382 mutate_func compress, mutate_func uncompress)
384 struct buf_state sbuf, *buf = &sbuf;
387 printf(" testing %s ...\n", name);
389 buf->orig_buf = (void *)plain;
390 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
391 errcheck(buf->orig_size > 0);
393 buf->compressed_size = TEST_BUFFER_SIZE;
394 buf->uncompressed_size = TEST_BUFFER_SIZE;
395 buf->compressed_buf = malloc(buf->compressed_size);
396 errcheck(buf->compressed_buf);
397 buf->uncompressed_buf = malloc(buf->uncompressed_size);
398 errcheck(buf->uncompressed_buf);
399 buf->compare_buf = malloc(buf->uncompressed_size);
400 errcheck(buf->compare_buf);
402 ret = run_test_internal(uts, name, compress, uncompress, buf);
404 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
406 free(buf->compare_buf);
407 free(buf->uncompressed_buf);
408 free(buf->compressed_buf);
413 static int compression_test_gzip(struct unit_test_state *uts)
415 return run_test(uts, "gzip", compress_using_gzip,
416 uncompress_using_gzip);
418 COMPRESSION_TEST(compression_test_gzip, 0);
420 static int compression_test_bzip2(struct unit_test_state *uts)
422 return run_test(uts, "bzip2", compress_using_bzip2,
423 uncompress_using_bzip2);
425 COMPRESSION_TEST(compression_test_bzip2, 0);
427 static int compression_test_lzma(struct unit_test_state *uts)
429 return run_test(uts, "lzma", compress_using_lzma,
430 uncompress_using_lzma);
432 COMPRESSION_TEST(compression_test_lzma, 0);
434 static int compression_test_lzo(struct unit_test_state *uts)
436 return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
438 COMPRESSION_TEST(compression_test_lzo, 0);
440 static int compression_test_lz4(struct unit_test_state *uts)
442 return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
444 COMPRESSION_TEST(compression_test_lz4, 0);
446 static int compress_using_none(struct unit_test_state *uts,
447 void *in, unsigned long in_size,
448 void *out, unsigned long out_max,
449 unsigned long *out_size)
451 /* Here we just copy */
452 memcpy(out, in, in_size);
459 * run_bootm_test() - Run tests on the bootm decompression function
461 * @comp_type: Compression type to test
462 * @compress: Our function to compress data
463 * Return: 0 if OK, non-zero on failure
465 static int run_bootm_test(struct unit_test_state *uts, int comp_type,
466 mutate_func compress)
468 ulong compress_size = 1024;
472 const ulong image_start = 0;
473 const ulong load_addr = 0x1000;
476 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
477 compress_buff = map_sysmem(image_start, 0);
478 unc_len = strlen(plain);
479 compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
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,
486 err = image_decomp(comp_type, load_addr, image_start,
487 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
488 compress_buff, compress_size, unc_len - 1,
492 /* We can't detect corruption when not decompressing */
493 if (comp_type == IH_COMP_NONE)
495 memset(compress_buff + compress_size / 2, '\x49',
497 err = image_decomp(comp_type, load_addr, image_start,
498 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
499 compress_buff, compress_size, 0x10000,
506 static int compression_test_bootm_gzip(struct unit_test_state *uts)
508 return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
510 COMPRESSION_TEST(compression_test_bootm_gzip, 0);
512 static int compression_test_bootm_bzip2(struct unit_test_state *uts)
514 return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
516 COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
518 static int compression_test_bootm_lzma(struct unit_test_state *uts)
520 return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
522 COMPRESSION_TEST(compression_test_bootm_lzma, 0);
524 static int compression_test_bootm_lzo(struct unit_test_state *uts)
526 return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
528 COMPRESSION_TEST(compression_test_bootm_lzo, 0);
530 static int compression_test_bootm_lz4(struct unit_test_state *uts)
532 return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
534 COMPRESSION_TEST(compression_test_bootm_lz4, 0);
536 static int compression_test_bootm_none(struct unit_test_state *uts)
538 return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
540 COMPRESSION_TEST(compression_test_bootm_none, 0);
542 int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
545 struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
546 const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
548 return cmd_ut_category("compression", "compression_test_",
549 tests, n_ents, argc, argv);