]> git.sur5r.net Git - u-boot/blob - test/compression.c
dm: usb: Adjust the USB_DEVICE() macro naming
[u-boot] / test / compression.c
1 /*
2  * Copyright (c) 2013, The Chromium Authors
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
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
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"
33         "messages.\n";
34
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;
53
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;
72
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;
97
98
99 #define TEST_BUFFER_SIZE        512
100
101 typedef int (*mutate_func)(void *, unsigned long, void *, unsigned long,
102                            unsigned long *);
103
104 static int compress_using_gzip(void *in, unsigned long in_size,
105                                void *out, unsigned long out_max,
106                                unsigned long *out_size)
107 {
108         int ret;
109         unsigned long inout_size = out_max;
110
111         ret = gzip(out, &inout_size, in, in_size);
112         if (out_size)
113                 *out_size = inout_size;
114
115         return ret;
116 }
117
118 static int uncompress_using_gzip(void *in, unsigned long in_size,
119                                  void *out, unsigned long out_max,
120                                  unsigned long *out_size)
121 {
122         int ret;
123         unsigned long inout_size = in_size;
124
125         ret = gunzip(out, out_max, in, &inout_size);
126         if (out_size)
127                 *out_size = inout_size;
128
129         return ret;
130 }
131
132 static int compress_using_bzip2(void *in, unsigned long in_size,
133                                 void *out, unsigned long out_max,
134                                 unsigned long *out_size)
135 {
136         /* There is no bzip2 compression in u-boot, so fake it. */
137         assert(in_size == strlen(plain));
138         assert(memcmp(plain, in, in_size) == 0);
139
140         if (bzip2_compressed_size > out_max)
141                 return -1;
142
143         memcpy(out, bzip2_compressed, bzip2_compressed_size);
144         if (out_size)
145                 *out_size = bzip2_compressed_size;
146
147         return 0;
148 }
149
150 static int uncompress_using_bzip2(void *in, unsigned long in_size,
151                                   void *out, unsigned long out_max,
152                                   unsigned long *out_size)
153 {
154         int ret;
155         unsigned int inout_size = out_max;
156
157         ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
158                         CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
159         if (out_size)
160                 *out_size = inout_size;
161
162         return (ret != BZ_OK);
163 }
164
165 static int compress_using_lzma(void *in, unsigned long in_size,
166                                void *out, unsigned long out_max,
167                                unsigned long *out_size)
168 {
169         /* There is no lzma compression in u-boot, so fake it. */
170         assert(in_size == strlen(plain));
171         assert(memcmp(plain, in, in_size) == 0);
172
173         if (lzma_compressed_size > out_max)
174                 return -1;
175
176         memcpy(out, lzma_compressed, lzma_compressed_size);
177         if (out_size)
178                 *out_size = lzma_compressed_size;
179
180         return 0;
181 }
182
183 static int uncompress_using_lzma(void *in, unsigned long in_size,
184                                  void *out, unsigned long out_max,
185                                  unsigned long *out_size)
186 {
187         int ret;
188         SizeT inout_size = out_max;
189
190         ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
191         if (out_size)
192                 *out_size = inout_size;
193
194         return (ret != SZ_OK);
195 }
196
197 static int compress_using_lzo(void *in, unsigned long in_size,
198                               void *out, unsigned long out_max,
199                               unsigned long *out_size)
200 {
201         /* There is no lzo compression in u-boot, so fake it. */
202         assert(in_size == strlen(plain));
203         assert(memcmp(plain, in, in_size) == 0);
204
205         if (lzo_compressed_size > out_max)
206                 return -1;
207
208         memcpy(out, lzo_compressed, lzo_compressed_size);
209         if (out_size)
210                 *out_size = lzo_compressed_size;
211
212         return 0;
213 }
214
215 static int uncompress_using_lzo(void *in, unsigned long in_size,
216                                 void *out, unsigned long out_max,
217                                 unsigned long *out_size)
218 {
219         int ret;
220         size_t input_size = in_size;
221         size_t output_size = out_max;
222
223         ret = lzop_decompress(in, input_size, out, &output_size);
224         if (out_size)
225                 *out_size = output_size;
226
227         return (ret != LZO_E_OK);
228 }
229
230 #define errcheck(statement) if (!(statement)) { \
231         fprintf(stderr, "\tFailed: %s\n", #statement); \
232         ret = 1; \
233         goto out; \
234 }
235
236 static int run_test(char *name, mutate_func compress, mutate_func uncompress)
237 {
238         ulong orig_size, compressed_size, uncompressed_size;
239         void *orig_buf;
240         void *compressed_buf = NULL;
241         void *uncompressed_buf = NULL;
242         void *compare_buf = NULL;
243         int ret;
244
245         printf(" testing %s ...\n", name);
246
247         orig_buf = (void *)plain;
248         orig_size = strlen(orig_buf); /* Trailing NULL not included. */
249         errcheck(orig_size > 0);
250
251         compressed_size = uncompressed_size = TEST_BUFFER_SIZE;
252         compressed_buf = malloc(compressed_size);
253         errcheck(compressed_buf != NULL);
254         uncompressed_buf = malloc(uncompressed_size);
255         errcheck(uncompressed_buf != NULL);
256         compare_buf = malloc(uncompressed_size);
257         errcheck(compare_buf != NULL);
258
259         /* Compress works as expected. */
260         printf("\torig_size:%lu\n", orig_size);
261         memset(compressed_buf, 'A', TEST_BUFFER_SIZE);
262         errcheck(compress(orig_buf, orig_size,
263                         compressed_buf, compressed_size,
264                         &compressed_size) == 0);
265         printf("\tcompressed_size:%lu\n", compressed_size);
266         errcheck(compressed_size > 0);
267         errcheck(compressed_size < orig_size);
268         errcheck(((char *)compressed_buf)[compressed_size-1] != 'A');
269         errcheck(((char *)compressed_buf)[compressed_size] == 'A');
270
271         /* Uncompresses with space remaining. */
272         errcheck(uncompress(compressed_buf, compressed_size,
273                           uncompressed_buf, uncompressed_size,
274                           &uncompressed_size) == 0);
275         printf("\tuncompressed_size:%lu\n", uncompressed_size);
276         errcheck(uncompressed_size == orig_size);
277         errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
278
279         /* Uncompresses with exactly the right size output buffer. */
280         memset(uncompressed_buf, 'A', TEST_BUFFER_SIZE);
281         errcheck(uncompress(compressed_buf, compressed_size,
282                           uncompressed_buf, orig_size,
283                           &uncompressed_size) == 0);
284         errcheck(uncompressed_size == orig_size);
285         errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
286         errcheck(((char *)uncompressed_buf)[orig_size] == 'A');
287
288         /* Make sure compression does not over-run. */
289         memset(compare_buf, 'A', TEST_BUFFER_SIZE);
290         ret = compress(orig_buf, orig_size,
291                        compare_buf, compressed_size - 1,
292                        NULL);
293         errcheck(((char *)compare_buf)[compressed_size] == 'A');
294         errcheck(ret != 0);
295         printf("\tcompress does not overrun\n");
296
297         /* Make sure decompression does not over-run. */
298         memset(compare_buf, 'A', TEST_BUFFER_SIZE);
299         ret = uncompress(compressed_buf, compressed_size,
300                          compare_buf, uncompressed_size - 1,
301                          NULL);
302         errcheck(((char *)compare_buf)[uncompressed_size - 1] == 'A');
303         errcheck(ret != 0);
304         printf("\tuncompress does not overrun\n");
305
306         /* Got here, everything is fine. */
307         ret = 0;
308
309 out:
310         printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
311
312         free(compare_buf);
313         free(uncompressed_buf);
314         free(compressed_buf);
315
316         return ret;
317 }
318
319 static int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc,
320                              char *const argv[])
321 {
322         int err = 0;
323
324         err += run_test("gzip", compress_using_gzip, uncompress_using_gzip);
325         err += run_test("bzip2", compress_using_bzip2, uncompress_using_bzip2);
326         err += run_test("lzma", compress_using_lzma, uncompress_using_lzma);
327         err += run_test("lzo", compress_using_lzo, uncompress_using_lzo);
328
329         printf("ut_compression %s\n", err == 0 ? "ok" : "FAILED");
330
331         return err;
332 }
333
334 static int compress_using_none(void *in, unsigned long in_size,
335                                void *out, unsigned long out_max,
336                                unsigned long *out_size)
337 {
338         /* Here we just copy */
339         memcpy(out, in, in_size);
340         *out_size = in_size;
341
342         return 0;
343 }
344
345 /**
346  * run_bootm_test() - Run tests on the bootm decopmression function
347  *
348  * @comp_type:  Compression type to test
349  * @compress:   Our function to compress data
350  * @return 0 if OK, non-zero on failure
351  */
352 static int run_bootm_test(int comp_type, mutate_func compress)
353 {
354         ulong compress_size = 1024;
355         void *compress_buff;
356         int unc_len;
357         int err = 0;
358         const ulong image_start = 0;
359         const ulong load_addr = 0x1000;
360         ulong load_end;
361
362         printf("Testing: %s\n", genimg_get_comp_name(comp_type));
363         compress_buff = map_sysmem(image_start, 0);
364         unc_len = strlen(plain);
365         compress((void *)plain, unc_len, compress_buff, compress_size,
366                  &compress_size);
367         err = bootm_decomp_image(comp_type, load_addr, image_start,
368                                  IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
369                                  compress_buff, compress_size, unc_len,
370                                  &load_end);
371         if (err)
372                 return err;
373         err = bootm_decomp_image(comp_type, load_addr, image_start,
374                                  IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
375                                  compress_buff, compress_size, unc_len - 1,
376                                  &load_end);
377         if (!err)
378                 return -EINVAL;
379
380         /* We can't detect corruption when not decompressing */
381         if (comp_type == IH_COMP_NONE)
382                 return 0;
383         memset(compress_buff + compress_size / 2, '\x49',
384                compress_size / 2);
385         err = bootm_decomp_image(comp_type, load_addr, image_start,
386                                  IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
387                                  compress_buff, compress_size, 0x10000,
388                                  &load_end);
389         if (!err)
390                 return -EINVAL;
391
392         return 0;
393 }
394
395 static int do_ut_image_decomp(cmd_tbl_t *cmdtp, int flag, int argc,
396                               char *const argv[])
397 {
398         int err = 0;
399
400         err = run_bootm_test(IH_COMP_GZIP, compress_using_gzip);
401         err |= run_bootm_test(IH_COMP_BZIP2, compress_using_bzip2);
402         err |= run_bootm_test(IH_COMP_LZMA, compress_using_lzma);
403         err |= run_bootm_test(IH_COMP_LZO, compress_using_lzo);
404         err |= run_bootm_test(IH_COMP_NONE, compress_using_none);
405
406         printf("ut_image_decomp %s\n", err == 0 ? "ok" : "FAILED");
407
408         return 0;
409 }
410
411 U_BOOT_CMD(
412         ut_compression, 5,      1,      do_ut_compression,
413         "Basic test of compressors: gzip bzip2 lzma lzo", ""
414 );
415
416 U_BOOT_CMD(
417         ut_image_decomp,        5,      1, do_ut_image_decomp,
418         "Basic test of bootm decompression", ""
419 );