2 * Copyright (c) 2013, The Chromium Authors
4 * SPDX-License-Identifier: GPL-2.0+
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>
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)(void *, unsigned long, void *, unsigned long,
126 static int compress_using_gzip(void *in, unsigned long in_size,
127 void *out, unsigned long out_max,
128 unsigned long *out_size)
131 unsigned long inout_size = out_max;
133 ret = gzip(out, &inout_size, in, in_size);
135 *out_size = inout_size;
140 static int uncompress_using_gzip(void *in, unsigned long in_size,
141 void *out, unsigned long out_max,
142 unsigned long *out_size)
145 unsigned long inout_size = in_size;
147 ret = gunzip(out, out_max, in, &inout_size);
149 *out_size = inout_size;
154 static int compress_using_bzip2(void *in, unsigned long in_size,
155 void *out, unsigned long out_max,
156 unsigned long *out_size)
158 /* There is no bzip2 compression in u-boot, so fake it. */
159 assert(in_size == strlen(plain));
160 assert(memcmp(plain, in, in_size) == 0);
162 if (bzip2_compressed_size > out_max)
165 memcpy(out, bzip2_compressed, bzip2_compressed_size);
167 *out_size = bzip2_compressed_size;
172 static int uncompress_using_bzip2(void *in, unsigned long in_size,
173 void *out, unsigned long out_max,
174 unsigned long *out_size)
177 unsigned int inout_size = out_max;
179 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
180 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
182 *out_size = inout_size;
184 return (ret != BZ_OK);
187 static int compress_using_lzma(void *in, unsigned long in_size,
188 void *out, unsigned long out_max,
189 unsigned long *out_size)
191 /* There is no lzma compression in u-boot, so fake it. */
192 assert(in_size == strlen(plain));
193 assert(memcmp(plain, in, in_size) == 0);
195 if (lzma_compressed_size > out_max)
198 memcpy(out, lzma_compressed, lzma_compressed_size);
200 *out_size = lzma_compressed_size;
205 static int uncompress_using_lzma(void *in, unsigned long in_size,
206 void *out, unsigned long out_max,
207 unsigned long *out_size)
210 SizeT inout_size = out_max;
212 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
214 *out_size = inout_size;
216 return (ret != SZ_OK);
219 static int compress_using_lzo(void *in, unsigned long in_size,
220 void *out, unsigned long out_max,
221 unsigned long *out_size)
223 /* There is no lzo compression in u-boot, so fake it. */
224 assert(in_size == strlen(plain));
225 assert(memcmp(plain, in, in_size) == 0);
227 if (lzo_compressed_size > out_max)
230 memcpy(out, lzo_compressed, lzo_compressed_size);
232 *out_size = lzo_compressed_size;
237 static int uncompress_using_lzo(void *in, unsigned long in_size,
238 void *out, unsigned long out_max,
239 unsigned long *out_size)
242 size_t input_size = in_size;
243 size_t output_size = out_max;
245 ret = lzop_decompress(in, input_size, out, &output_size);
247 *out_size = output_size;
249 return (ret != LZO_E_OK);
252 static int compress_using_lz4(void *in, unsigned long in_size,
253 void *out, unsigned long out_max,
254 unsigned long *out_size)
256 /* There is no lz4 compression in u-boot, so fake it. */
257 assert(in_size == strlen(plain));
258 assert(memcmp(plain, in, in_size) == 0);
260 if (lz4_compressed_size > out_max)
263 memcpy(out, lz4_compressed, lz4_compressed_size);
265 *out_size = lz4_compressed_size;
270 static int uncompress_using_lz4(void *in, unsigned long in_size,
271 void *out, unsigned long out_max,
272 unsigned long *out_size)
275 size_t input_size = in_size;
276 size_t output_size = out_max;
278 ret = ulz4fn(in, input_size, out, &output_size);
280 *out_size = output_size;
285 #define errcheck(statement) if (!(statement)) { \
286 fprintf(stderr, "\tFailed: %s\n", #statement); \
291 static int run_test(char *name, mutate_func compress, mutate_func uncompress)
293 ulong orig_size, compressed_size, uncompressed_size;
295 void *compressed_buf = NULL;
296 void *uncompressed_buf = NULL;
297 void *compare_buf = NULL;
300 printf(" testing %s ...\n", name);
302 orig_buf = (void *)plain;
303 orig_size = strlen(orig_buf); /* Trailing NULL not included. */
304 errcheck(orig_size > 0);
306 compressed_size = uncompressed_size = TEST_BUFFER_SIZE;
307 compressed_buf = malloc(compressed_size);
308 errcheck(compressed_buf != NULL);
309 uncompressed_buf = malloc(uncompressed_size);
310 errcheck(uncompressed_buf != NULL);
311 compare_buf = malloc(uncompressed_size);
312 errcheck(compare_buf != NULL);
314 /* Compress works as expected. */
315 printf("\torig_size:%lu\n", orig_size);
316 memset(compressed_buf, 'A', TEST_BUFFER_SIZE);
317 errcheck(compress(orig_buf, orig_size,
318 compressed_buf, compressed_size,
319 &compressed_size) == 0);
320 printf("\tcompressed_size:%lu\n", compressed_size);
321 errcheck(compressed_size > 0);
322 errcheck(compressed_size < orig_size);
323 errcheck(((char *)compressed_buf)[compressed_size-1] != 'A');
324 errcheck(((char *)compressed_buf)[compressed_size] == 'A');
326 /* Uncompresses with space remaining. */
327 errcheck(uncompress(compressed_buf, compressed_size,
328 uncompressed_buf, uncompressed_size,
329 &uncompressed_size) == 0);
330 printf("\tuncompressed_size:%lu\n", uncompressed_size);
331 errcheck(uncompressed_size == orig_size);
332 errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
334 /* Uncompresses with exactly the right size output buffer. */
335 memset(uncompressed_buf, 'A', TEST_BUFFER_SIZE);
336 errcheck(uncompress(compressed_buf, compressed_size,
337 uncompressed_buf, orig_size,
338 &uncompressed_size) == 0);
339 errcheck(uncompressed_size == orig_size);
340 errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
341 errcheck(((char *)uncompressed_buf)[orig_size] == 'A');
343 /* Make sure compression does not over-run. */
344 memset(compare_buf, 'A', TEST_BUFFER_SIZE);
345 ret = compress(orig_buf, orig_size,
346 compare_buf, compressed_size - 1,
348 errcheck(((char *)compare_buf)[compressed_size] == 'A');
350 printf("\tcompress does not overrun\n");
352 /* Make sure decompression does not over-run. */
353 memset(compare_buf, 'A', TEST_BUFFER_SIZE);
354 ret = uncompress(compressed_buf, compressed_size,
355 compare_buf, uncompressed_size - 1,
357 errcheck(((char *)compare_buf)[uncompressed_size - 1] == 'A');
359 printf("\tuncompress does not overrun\n");
361 /* Got here, everything is fine. */
365 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
368 free(uncompressed_buf);
369 free(compressed_buf);
374 static int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc,
379 err += run_test("gzip", compress_using_gzip, uncompress_using_gzip);
380 err += run_test("bzip2", compress_using_bzip2, uncompress_using_bzip2);
381 err += run_test("lzma", compress_using_lzma, uncompress_using_lzma);
382 err += run_test("lzo", compress_using_lzo, uncompress_using_lzo);
383 err += run_test("lz4", compress_using_lz4, uncompress_using_lz4);
385 printf("ut_compression %s\n", err == 0 ? "ok" : "FAILED");
390 static int compress_using_none(void *in, unsigned long in_size,
391 void *out, unsigned long out_max,
392 unsigned long *out_size)
394 /* Here we just copy */
395 memcpy(out, in, in_size);
402 * run_bootm_test() - Run tests on the bootm decopmression function
404 * @comp_type: Compression type to test
405 * @compress: Our function to compress data
406 * @return 0 if OK, non-zero on failure
408 static int run_bootm_test(int comp_type, mutate_func compress)
410 ulong compress_size = 1024;
414 const ulong image_start = 0;
415 const ulong load_addr = 0x1000;
418 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
419 compress_buff = map_sysmem(image_start, 0);
420 unc_len = strlen(plain);
421 compress((void *)plain, unc_len, compress_buff, compress_size,
423 err = bootm_decomp_image(comp_type, load_addr, image_start,
424 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
425 compress_buff, compress_size, unc_len,
429 err = bootm_decomp_image(comp_type, load_addr, image_start,
430 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
431 compress_buff, compress_size, unc_len - 1,
436 /* We can't detect corruption when not decompressing */
437 if (comp_type == IH_COMP_NONE)
439 memset(compress_buff + compress_size / 2, '\x49',
441 err = bootm_decomp_image(comp_type, load_addr, image_start,
442 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
443 compress_buff, compress_size, 0x10000,
451 static int do_ut_image_decomp(cmd_tbl_t *cmdtp, int flag, int argc,
456 err = run_bootm_test(IH_COMP_GZIP, compress_using_gzip);
457 err |= run_bootm_test(IH_COMP_BZIP2, compress_using_bzip2);
458 err |= run_bootm_test(IH_COMP_LZMA, compress_using_lzma);
459 err |= run_bootm_test(IH_COMP_LZO, compress_using_lzo);
460 err |= run_bootm_test(IH_COMP_LZ4, compress_using_lz4);
461 err |= run_bootm_test(IH_COMP_NONE, compress_using_none);
463 printf("ut_image_decomp %s\n", err == 0 ? "ok" : "FAILED");
469 ut_compression, 5, 1, do_ut_compression,
470 "Basic test of compressors: gzip bzip2 lzma lzo", ""
474 ut_image_decomp, 5, 1, do_ut_image_decomp,
475 "Basic test of bootm decompression", ""