1
2
3
4
5
6
7#define DEBUG
8
9#include <common.h>
10#include <bootm.h>
11#include <command.h>
12#include <malloc.h>
13#include <mapmem.h>
14#include <asm/io.h>
15
16#include <u-boot/zlib.h>
17#include <bzlib.h>
18
19#include <lzma/LzmaTypes.h>
20#include <lzma/LzmaDec.h>
21#include <lzma/LzmaTools.h>
22
23#include <linux/lzo.h>
24
25static 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"
33 "messages.\n";
34
35
36static 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";
52static const unsigned long bzip2_compressed_size = 240;
53
54
55static 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";
71static const unsigned long lzma_compressed_size = 229;
72
73
74static 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";
96static const unsigned long lzo_compressed_size = 334;
97
98
99static 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"
117 "\x9d\x12\x8c\x9d";
118static const unsigned long lz4_compressed_size = 276;
119
120
121#define TEST_BUFFER_SIZE 512
122
123typedef int (*mutate_func)(void *, unsigned long, void *, unsigned long,
124 unsigned long *);
125
126static int compress_using_gzip(void *in, unsigned long in_size,
127 void *out, unsigned long out_max,
128 unsigned long *out_size)
129{
130 int ret;
131 unsigned long inout_size = out_max;
132
133 ret = gzip(out, &inout_size, in, in_size);
134 if (out_size)
135 *out_size = inout_size;
136
137 return ret;
138}
139
140static int uncompress_using_gzip(void *in, unsigned long in_size,
141 void *out, unsigned long out_max,
142 unsigned long *out_size)
143{
144 int ret;
145 unsigned long inout_size = in_size;
146
147 ret = gunzip(out, out_max, in, &inout_size);
148 if (out_size)
149 *out_size = inout_size;
150
151 return ret;
152}
153
154static int compress_using_bzip2(void *in, unsigned long in_size,
155 void *out, unsigned long out_max,
156 unsigned long *out_size)
157{
158
159 assert(in_size == strlen(plain));
160 assert(memcmp(plain, in, in_size) == 0);
161
162 if (bzip2_compressed_size > out_max)
163 return -1;
164
165 memcpy(out, bzip2_compressed, bzip2_compressed_size);
166 if (out_size)
167 *out_size = bzip2_compressed_size;
168
169 return 0;
170}
171
172static int uncompress_using_bzip2(void *in, unsigned long in_size,
173 void *out, unsigned long out_max,
174 unsigned long *out_size)
175{
176 int ret;
177 unsigned int inout_size = out_max;
178
179 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
180 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
181 if (out_size)
182 *out_size = inout_size;
183
184 return (ret != BZ_OK);
185}
186
187static int compress_using_lzma(void *in, unsigned long in_size,
188 void *out, unsigned long out_max,
189 unsigned long *out_size)
190{
191
192 assert(in_size == strlen(plain));
193 assert(memcmp(plain, in, in_size) == 0);
194
195 if (lzma_compressed_size > out_max)
196 return -1;
197
198 memcpy(out, lzma_compressed, lzma_compressed_size);
199 if (out_size)
200 *out_size = lzma_compressed_size;
201
202 return 0;
203}
204
205static int uncompress_using_lzma(void *in, unsigned long in_size,
206 void *out, unsigned long out_max,
207 unsigned long *out_size)
208{
209 int ret;
210 SizeT inout_size = out_max;
211
212 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
213 if (out_size)
214 *out_size = inout_size;
215
216 return (ret != SZ_OK);
217}
218
219static int compress_using_lzo(void *in, unsigned long in_size,
220 void *out, unsigned long out_max,
221 unsigned long *out_size)
222{
223
224 assert(in_size == strlen(plain));
225 assert(memcmp(plain, in, in_size) == 0);
226
227 if (lzo_compressed_size > out_max)
228 return -1;
229
230 memcpy(out, lzo_compressed, lzo_compressed_size);
231 if (out_size)
232 *out_size = lzo_compressed_size;
233
234 return 0;
235}
236
237static int uncompress_using_lzo(void *in, unsigned long in_size,
238 void *out, unsigned long out_max,
239 unsigned long *out_size)
240{
241 int ret;
242 size_t input_size = in_size;
243 size_t output_size = out_max;
244
245 ret = lzop_decompress(in, input_size, out, &output_size);
246 if (out_size)
247 *out_size = output_size;
248
249 return (ret != LZO_E_OK);
250}
251
252static int compress_using_lz4(void *in, unsigned long in_size,
253 void *out, unsigned long out_max,
254 unsigned long *out_size)
255{
256
257 assert(in_size == strlen(plain));
258 assert(memcmp(plain, in, in_size) == 0);
259
260 if (lz4_compressed_size > out_max)
261 return -1;
262
263 memcpy(out, lz4_compressed, lz4_compressed_size);
264 if (out_size)
265 *out_size = lz4_compressed_size;
266
267 return 0;
268}
269
270static int uncompress_using_lz4(void *in, unsigned long in_size,
271 void *out, unsigned long out_max,
272 unsigned long *out_size)
273{
274 int ret;
275 size_t input_size = in_size;
276 size_t output_size = out_max;
277
278 ret = ulz4fn(in, input_size, out, &output_size);
279 if (out_size)
280 *out_size = output_size;
281
282 return (ret != 0);
283}
284
285#define errcheck(statement) if (!(statement)) { \
286 fprintf(stderr, "\tFailed: %s\n", #statement); \
287 ret = 1; \
288 goto out; \
289}
290
291static int run_test(char *name, mutate_func compress, mutate_func uncompress)
292{
293 ulong orig_size, compressed_size, uncompressed_size;
294 void *orig_buf;
295 void *compressed_buf = NULL;
296 void *uncompressed_buf = NULL;
297 void *compare_buf = NULL;
298 int ret;
299
300 printf(" testing %s ...\n", name);
301
302 orig_buf = (void *)plain;
303 orig_size = strlen(orig_buf);
304 errcheck(orig_size > 0);
305
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);
313
314
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');
325
326
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);
333
334
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');
342
343
344 memset(compare_buf, 'A', TEST_BUFFER_SIZE);
345 ret = compress(orig_buf, orig_size,
346 compare_buf, compressed_size - 1,
347 NULL);
348 errcheck(((char *)compare_buf)[compressed_size] == 'A');
349 errcheck(ret != 0);
350 printf("\tcompress does not overrun\n");
351
352
353 memset(compare_buf, 'A', TEST_BUFFER_SIZE);
354 ret = uncompress(compressed_buf, compressed_size,
355 compare_buf, uncompressed_size - 1,
356 NULL);
357 errcheck(((char *)compare_buf)[uncompressed_size - 1] == 'A');
358 errcheck(ret != 0);
359 printf("\tuncompress does not overrun\n");
360
361
362 ret = 0;
363
364out:
365 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
366
367 free(compare_buf);
368 free(uncompressed_buf);
369 free(compressed_buf);
370
371 return ret;
372}
373
374static int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc,
375 char *const argv[])
376{
377 int err = 0;
378
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);
384
385 printf("ut_compression %s\n", err == 0 ? "ok" : "FAILED");
386
387 return err;
388}
389
390static int compress_using_none(void *in, unsigned long in_size,
391 void *out, unsigned long out_max,
392 unsigned long *out_size)
393{
394
395 memcpy(out, in, in_size);
396 *out_size = in_size;
397
398 return 0;
399}
400
401
402
403
404
405
406
407
408static int run_bootm_test(int comp_type, mutate_func compress)
409{
410 ulong compress_size = 1024;
411 void *compress_buff;
412 int unc_len;
413 int err = 0;
414 const ulong image_start = 0;
415 const ulong load_addr = 0x1000;
416 ulong load_end;
417
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,
422 &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,
426 &load_end);
427 if (err)
428 return err;
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,
432 &load_end);
433 if (!err)
434 return -EINVAL;
435
436
437 if (comp_type == IH_COMP_NONE)
438 return 0;
439 memset(compress_buff + compress_size / 2, '\x49',
440 compress_size / 2);
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,
444 &load_end);
445 if (!err)
446 return -EINVAL;
447
448 return 0;
449}
450
451static int do_ut_image_decomp(cmd_tbl_t *cmdtp, int flag, int argc,
452 char *const argv[])
453{
454 int err = 0;
455
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);
462
463 printf("ut_image_decomp %s\n", err == 0 ? "ok" : "FAILED");
464
465 return 0;
466}
467
468U_BOOT_CMD(
469 ut_compression, 5, 1, do_ut_compression,
470 "Basic test of compressors: gzip bzip2 lzma lzo", ""
471);
472
473U_BOOT_CMD(
474 ut_image_decomp, 5, 1, do_ut_image_decomp,
475 "Basic test of bootm decompression", ""
476);
477