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); \
293 ulong compressed_size;
294 ulong uncompressed_size;
296 void *compressed_buf;
297 void *uncompressed_buf;
301 static int run_test_internal(char *name,
302 mutate_func compress, mutate_func uncompress,
303 struct buf_state *buf)
307 /* Compress works as expected. */
308 printf("\torig_size:%lu\n", buf->orig_size);
309 memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
310 errcheck(compress(buf->orig_buf, buf->orig_size, buf->compressed_buf,
311 buf->compressed_size, &buf->compressed_size) == 0);
312 printf("\tcompressed_size:%lu\n", buf->compressed_size);
313 errcheck(buf->compressed_size > 0);
314 errcheck(buf->compressed_size < buf->orig_size);
315 errcheck(((char *)buf->compressed_buf)[buf->compressed_size - 1] !=
317 errcheck(((char *)buf->compressed_buf)[buf->compressed_size] == 'A');
319 /* Uncompresses with space remaining. */
320 errcheck(uncompress(buf->compressed_buf, buf->compressed_size,
321 buf->uncompressed_buf, buf->uncompressed_size,
322 &buf->uncompressed_size) == 0);
323 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
324 errcheck(buf->uncompressed_size == buf->orig_size);
325 errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
326 buf->orig_size) == 0);
328 /* Uncompresses with exactly the right size output buffer. */
329 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
330 errcheck(uncompress(buf->compressed_buf, buf->compressed_size,
331 buf->uncompressed_buf, buf->orig_size,
332 &buf->uncompressed_size) == 0);
333 errcheck(buf->uncompressed_size == buf->orig_size);
334 errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
335 buf->orig_size) == 0);
336 errcheck(((char *)buf->uncompressed_buf)[buf->orig_size] == 'A');
338 /* Make sure compression does not over-run. */
339 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
340 ret = compress(buf->orig_buf, buf->orig_size,
341 buf->compare_buf, buf->compressed_size - 1,
343 errcheck(((char *)buf->compare_buf)[buf->compressed_size] == 'A');
345 printf("\tcompress does not overrun\n");
347 /* Make sure decompression does not over-run. */
348 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
349 ret = uncompress(buf->compressed_buf, buf->compressed_size,
350 buf->compare_buf, buf->uncompressed_size - 1,
352 errcheck(((char *)buf->compare_buf)[buf->uncompressed_size - 1] == 'A');
354 printf("\tuncompress does not overrun\n");
356 /* Got here, everything is fine. */
363 static int run_test(char *name, mutate_func compress, mutate_func uncompress)
365 struct buf_state sbuf, *buf = &sbuf;
368 printf(" testing %s ...\n", name);
370 buf->orig_buf = (void *)plain;
371 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
372 errcheck(buf->orig_size > 0);
374 buf->compressed_size = TEST_BUFFER_SIZE;
375 buf->uncompressed_size = TEST_BUFFER_SIZE;
376 buf->compressed_buf = malloc(buf->compressed_size);
377 errcheck(buf->compressed_buf);
378 buf->uncompressed_buf = malloc(buf->uncompressed_size);
379 errcheck(buf->uncompressed_buf);
380 buf->compare_buf = malloc(buf->uncompressed_size);
381 errcheck(buf->compare_buf);
383 ret = run_test_internal(name, compress, uncompress, buf);
385 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
387 free(buf->compare_buf);
388 free(buf->uncompressed_buf);
389 free(buf->compressed_buf);
394 static int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc,
399 err += run_test("gzip", compress_using_gzip, uncompress_using_gzip);
400 err += run_test("bzip2", compress_using_bzip2, uncompress_using_bzip2);
401 err += run_test("lzma", compress_using_lzma, uncompress_using_lzma);
402 err += run_test("lzo", compress_using_lzo, uncompress_using_lzo);
403 err += run_test("lz4", compress_using_lz4, uncompress_using_lz4);
405 printf("ut_compression %s\n", err == 0 ? "ok" : "FAILED");
410 static int compress_using_none(void *in, unsigned long in_size,
411 void *out, unsigned long out_max,
412 unsigned long *out_size)
414 /* Here we just copy */
415 memcpy(out, in, in_size);
422 * run_bootm_test() - Run tests on the bootm decopmression function
424 * @comp_type: Compression type to test
425 * @compress: Our function to compress data
426 * @return 0 if OK, non-zero on failure
428 static int run_bootm_test(int comp_type, mutate_func compress)
430 ulong compress_size = 1024;
434 const ulong image_start = 0;
435 const ulong load_addr = 0x1000;
438 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
439 compress_buff = map_sysmem(image_start, 0);
440 unc_len = strlen(plain);
441 compress((void *)plain, unc_len, compress_buff, compress_size,
443 err = bootm_decomp_image(comp_type, load_addr, image_start,
444 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
445 compress_buff, compress_size, unc_len,
449 err = bootm_decomp_image(comp_type, load_addr, image_start,
450 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
451 compress_buff, compress_size, unc_len - 1,
456 /* We can't detect corruption when not decompressing */
457 if (comp_type == IH_COMP_NONE)
459 memset(compress_buff + compress_size / 2, '\x49',
461 err = bootm_decomp_image(comp_type, load_addr, image_start,
462 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
463 compress_buff, compress_size, 0x10000,
471 static int do_ut_image_decomp(cmd_tbl_t *cmdtp, int flag, int argc,
476 err = run_bootm_test(IH_COMP_GZIP, compress_using_gzip);
477 err |= run_bootm_test(IH_COMP_BZIP2, compress_using_bzip2);
478 err |= run_bootm_test(IH_COMP_LZMA, compress_using_lzma);
479 err |= run_bootm_test(IH_COMP_LZO, compress_using_lzo);
480 err |= run_bootm_test(IH_COMP_LZ4, compress_using_lz4);
481 err |= run_bootm_test(IH_COMP_NONE, compress_using_none);
483 printf("ut_image_decomp %s\n", err == 0 ? "ok" : "FAILED");
489 ut_compression, 5, 1, do_ut_compression,
490 "Basic test of compressors: gzip bzip2 lzma lzo", ""
494 ut_image_decomp, 5, 1, do_ut_image_decomp,
495 "Basic test of bootm decompression", ""